X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Flcp.c;h=4542164d7ee96cc4695fec350d0ddebd8612ca83;hb=ce936f21261e7e5e098a1ddb4b36d8ba344976c3;hp=231b7e4552861ea828cb361e9923bccf83c061d3;hpb=2c872bc67b83b91ba6390f6e5e72be08e09811a1;p=ppp.git diff --git a/pppd/lcp.c b/pppd/lcp.c index 231b7e4..4542164 100644 --- a/pppd/lcp.c +++ b/pppd/lcp.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: lcp.c,v 1.48 2000/03/27 06:02:59 paulus Exp $"; +#define RCSID "$Id: lcp.c,v 1.56 2001/02/22 03:16:26 paulus Exp $" /* * TODO: @@ -35,17 +35,35 @@ static const char rcsid[] = RCSID; +/* + * When the link comes up we want to be able to wait for a short while, + * or until seeing some input from the peer, before starting to send + * configure-requests. We do this by delaying the fsm_lowerup call. + */ +/* steal a bit in fsm flags word */ +#define DELAYED_UP 0x100 + +static void lcp_delayed_up __P((void *)); + /* * LCP-related command-line options. */ int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ bool lax_recv = 0; /* accept control chars in asyncmap */ +bool noendpoint = 0; /* don't send/accept endpoint discriminator */ +static int noopt __P((char **)); static int setescape __P((char **)); +#ifdef HAVE_MULTILINK +static int setendpoint __P((char **)); +#endif /* HAVE_MULTILINK */ + static option_t lcp_option_list[] = { /* LCP options */ + { "-all", o_special_noarg, (void *)noopt, + "Don't request/allow any LCP options" }, { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, "Disable address/control compression", OPT_A2COPY, &lcp_allowoptions[0].neg_accompression }, @@ -79,6 +97,8 @@ static option_t lcp_option_list[] = { { "mru", o_int, &lcp_wantoptions[0].mru, "Set MRU (maximum received packet size) for negotiation", 0, &lcp_wantoptions[0].neg_mru }, + { "mtu", o_int, &lcp_allowoptions[0].mru, + "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, "Disable protocol field compression", OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression }, @@ -91,7 +111,7 @@ static option_t lcp_option_list[] = { "Set passive mode", 1 }, { "silent", o_bool, &lcp_wantoptions[0].silent, "Set silent mode", 1 }, - { "escape", o_special, setescape, + { "escape", o_special, (void *)setescape, "List of character codes to escape on transmission" }, { "lcp-echo-failure", o_int, &lcp_echo_fails, "Set number of consecutive echo failures to indicate link failure" }, @@ -108,13 +128,20 @@ static option_t lcp_option_list[] = { { "receive-all", o_bool, &lax_recv, "Accept all received control characters", 1 }, #ifdef HAVE_MULTILINK + { "mrru", o_int, &lcp_wantoptions[0].mrru, + "Maximum received packet size for multilink bundle", + 0, &lcp_wantoptions[0].neg_mrru }, { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, "Use short sequence numbers in multilink headers", - OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf }, + OPT_A2COPY | 1, &lcp_allowoptions[0].neg_ssnhf }, { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, "Don't use short sequence numbers in multilink headers", OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf }, + { "endpoint", o_special, setendpoint, + "Endpoint discriminator for multilink" }, #endif /* HAVE_MULTILINK */ + { "noendpoint", o_bool, &noendpoint, + "Don't send or accept multilink endpoint discriminator", 1 }, {NULL} }; @@ -124,7 +151,7 @@ lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ -u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */ +u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */ static int lcp_echos_pending = 0; /* Number of outstanding echo msgs */ static int lcp_echo_number = 0; /* ID number of next echo frame */ @@ -226,6 +253,18 @@ int lcp_loopbackfail = DEFLOOPBACKFAIL; #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ (x) == CONFNAK ? "NAK" : "REJ") +/* + * noopt - Disable all options (why?). + */ +static int +noopt(argv) + char **argv; +{ + BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); + BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); + + return (1); +} /* * setescape - add chars to the set we escape on transmission. @@ -258,6 +297,20 @@ setescape(argv) return ret; } +#ifdef HAVE_MULTILINK +static int +setendpoint(argv) + char **argv; +{ + if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { + lcp_wantoptions[0].neg_endpoint = 1; + return 1; + } + option_error("Can't parse '%s' as an endpoint discriminator", *argv); + return 0; +} +#endif /* HAVE_MULTILINK */ + /* * lcp_init - Initialize LCP. */ @@ -275,41 +328,31 @@ lcp_init(unit) fsm_init(f); - wo->passive = 0; - wo->silent = 0; - wo->restart = 0; /* Set to 1 in kernels or multi-line - implementations */ + BZERO(wo, sizeof(*wo)); wo->neg_mru = 1; wo->mru = DEFMRU; wo->neg_asyncmap = 1; - wo->asyncmap = 0; - wo->neg_chap = 0; /* Set to 1 on server */ - wo->neg_upap = 0; /* Set to 1 on server */ wo->chap_mdtype = CHAP_DIGEST_MD5; wo->neg_magicnumber = 1; wo->neg_pcompression = 1; wo->neg_accompression = 1; - wo->neg_lqr = 0; /* no LQR implementation yet */ - wo->neg_cbcp = 0; + BZERO(ao, sizeof(*ao)); ao->neg_mru = 1; ao->mru = MAXMRU; ao->neg_asyncmap = 1; - ao->asyncmap = 0; ao->neg_chap = 1; ao->chap_mdtype = CHAP_DIGEST_MD5; ao->neg_upap = 1; ao->neg_magicnumber = 1; ao->neg_pcompression = 1; ao->neg_accompression = 1; - ao->neg_lqr = 0; /* no LQR implementation yet */ #ifdef CBCP_SUPPORT ao->neg_cbcp = 1; -#else - ao->neg_cbcp = 0; #endif + ao->neg_endpoint = 1; - memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + BZERO(xmit_accm[unit], sizeof(xmit_accm[0])); xmit_accm[unit][3] = 0x60000000; } @@ -324,7 +367,7 @@ lcp_open(unit) fsm *f = &lcp_fsm[unit]; lcp_options *wo = &lcp_wantoptions[unit]; - f->flags = 0; + f->flags &= ~(OPT_PASSIVE | OPT_SILENT); if (wo->passive) f->flags |= OPT_PASSIVE; if (wo->silent) @@ -368,6 +411,7 @@ lcp_lowerup(unit) int unit; { lcp_options *wo = &lcp_wantoptions[unit]; + fsm *f = &lcp_fsm[unit]; /* * Don't use A/C or protocol compression on transmission, @@ -381,7 +425,11 @@ lcp_lowerup(unit) peer_mru[unit] = PPP_MRU; lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; - fsm_lowerup(&lcp_fsm[unit]); + if (listen_time != 0) { + f->flags |= DELAYED_UP; + timeout(lcp_delayed_up, f, 0, listen_time * 1000); + } else + fsm_lowerup(f); } @@ -392,7 +440,28 @@ void lcp_lowerdown(unit) int unit; { - fsm_lowerdown(&lcp_fsm[unit]); + fsm *f = &lcp_fsm[unit]; + + if (f->flags & DELAYED_UP) + f->flags &= ~DELAYED_UP; + else + fsm_lowerdown(&lcp_fsm[unit]); +} + + +/* + * lcp_delayed_up - Bring the lower layer up now. + */ +static void +lcp_delayed_up(arg) + void *arg; +{ + fsm *f = arg; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + fsm_lowerup(f); + } } @@ -407,6 +476,10 @@ lcp_input(unit, p, len) { fsm *f = &lcp_fsm[unit]; + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + fsm_lowerup(f); + } fsm_input(f, p, len); } @@ -539,12 +612,19 @@ lcp_resetci(f) fsm *f; { lcp_options *wo = &lcp_wantoptions[f->unit]; + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; wo->magicnumber = magic(); wo->numloops = 0; - if (!wo->neg_multilink) - wo->neg_ssnhf = 0; - lcp_gotoptions[f->unit] = *wo; + *go = *wo; + if (!multilink) { + go->neg_mrru = 0; + go->neg_ssnhf = 0; + go->neg_endpoint = 0; + } + if (noendpoint) + ao->neg_endpoint = 0; peer_mru[f->unit] = PPP_MRU; auth_reset(f->unit); } @@ -578,9 +658,9 @@ lcp_cilen(f) LENCILONG(go->neg_magicnumber) + LENCIVOID(go->neg_pcompression) + LENCIVOID(go->neg_accompression) + - LENCISHORT(go->neg_multilink) + + LENCISHORT(go->neg_mrru) + LENCIVOID(go->neg_ssnhf) + - (go->neg_endpoint? CILEN_CHAR + go->endp_len: 0)); + (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); } @@ -653,10 +733,10 @@ lcp_addci(f, ucp, lenp) ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); - ADDCISHORT(CI_MRRU, go->neg_multilink, go->mrru); + ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); ADDCIVOID(CI_SSNHF, go->neg_ssnhf); - ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endp_class, go->endpoint, - go->endp_len); + ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class, + go->endpoint.value, go->endpoint.length); if (ucp - start_ucp != *lenp) { /* this should never happen, because peer_mtu should be 1500 */ @@ -800,10 +880,10 @@ lcp_ackci(f, p, len) ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); - ACKCISHORT(CI_MRRU, go->neg_multilink, go->mrru); + ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); ACKCIVOID(CI_SSNHF, go->neg_ssnhf); - ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endp_class, go->endpoint, - go->endp_len); + ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class, + go->endpoint.value, go->endpoint.length); /* * If there are any remaining CIs, then this packet is bad. @@ -1052,8 +1132,8 @@ lcp_nakci(f, p, len) * Nak for MRRU option - accept their value if it is smaller * than the one we want. */ - if (go->neg_multilink) { - NAKCISHORT(CI_MRRU, neg_multilink, + if (go->neg_mrru) { + NAKCISHORT(CI_MRRU, neg_mrru, if (cishort <= wo->mrru) try.mrru = cishort; ); @@ -1134,7 +1214,7 @@ lcp_nakci(f, p, len) goto bad; break; case CI_MRRU: - if (go->neg_multilink || no.neg_multilink || cilen != CILEN_SHORT) + if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) goto bad; break; case CI_SSNHF: @@ -1286,7 +1366,7 @@ lcp_rejci(f, p, len) p[1] == CILEN_CHAR + vlen) { \ int i; \ len -= CILEN_CHAR + vlen; \ - INCPTR(p[1], p); \ + INCPTR(2, p); \ GETCHAR(cichar, p); \ if (cichar != class) \ goto bad; \ @@ -1309,10 +1389,10 @@ lcp_rejci(f, p, len) REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); REJCIVOID(CI_PCOMPRESSION, neg_pcompression); REJCIVOID(CI_ACCOMPRESSION, neg_accompression); - REJCISHORT(CI_MRRU, neg_multilink, go->mrru); + REJCISHORT(CI_MRRU, neg_mrru, go->mrru); REJCIVOID(CI_SSNHF, neg_ssnhf); - REJCIENDP(CI_EPDISC, neg_endpoint, go->endp_class, go->endpoint, - go->endp_len); + REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class, + go->endpoint.value, go->endpoint.length); /* * If there are any remaining CIs, then this packet is bad. @@ -1596,7 +1676,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; case CI_MRRU: - if (!ao->neg_multilink || + if (!ao->neg_mrru || !multilink || cilen != CILEN_SHORT) { orc = CONFREJ; break; @@ -1604,12 +1684,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) GETSHORT(cishort, p); /* possibly should insist on a minimum/maximum MRRU here */ - ho->neg_multilink = 1; + ho->neg_mrru = 1; ho->mrru = cishort; break; case CI_SSNHF: - if (!ao->neg_ssnhf || + if (!ao->neg_ssnhf || !multilink || cilen != CILEN_VOID) { orc = CONFREJ; break; @@ -1627,9 +1707,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) GETCHAR(cichar, p); cilen -= CILEN_CHAR; ho->neg_endpoint = 1; - ho->endp_class = cichar; - ho->endp_len = cilen; - BCOPY(p, ho->endpoint, cilen); + ho->endpoint.class = cichar; + ho->endpoint.length = cilen; + BCOPY(p, ho->endpoint.value, cilen); INCPTR(cilen, p); break; @@ -1783,10 +1863,6 @@ static char *lcp_codenames[] = { "EchoReq", "EchoRep", "DiscReq" }; -static char *endp_class_names[] = { - "null", "local", "IP", "MAC", "magic", "phone" -}; - static int lcp_printpkt(p, plen, printer, arg) u_char *p; @@ -1796,7 +1872,6 @@ lcp_printpkt(p, plen, printer, arg) { int code, id, len, olen, i; u_char *pstart, *optend; - u_char cichar; u_short cishort; u_int32_t cilong; @@ -1938,15 +2013,23 @@ lcp_printpkt(p, plen, printer, arg) } break; case CI_EPDISC: +#ifdef HAVE_MULTILINK if (olen >= CILEN_CHAR) { + struct epdisc epd; p += 2; - GETCHAR(cichar, p); - if (cichar <= 5) - printer(arg, "endpoint [%s]:", - endp_class_names[cichar]); - else - printer(arg, "endpoint [%d]:"); + GETCHAR(epd.class, p); + epd.length = olen - CILEN_CHAR; + if (epd.length > MAX_ENDP_LEN) + epd.length = MAX_ENDP_LEN; + if (epd.length > 0) { + BCOPY(p, epd.value, epd.length); + p += epd.length; + } + printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); } +#else + printer(arg, "endpoint"); +#endif break; } while (p < optend) { @@ -1961,7 +2044,7 @@ lcp_printpkt(p, plen, printer, arg) case TERMREQ: if (len > 0 && *p >= ' ' && *p < 0x7f) { printer(arg, " "); - print_string(p, len, printer, arg); + print_string((char *)p, len, printer, arg); p += len; len = 0; }