72 #define PPPOE_MAXMTU PPP_MAXMRU
79 int lcp_echo_interval = 0;
80 int lcp_echo_fails = 0;
83 static int setescape (
char **);
85 static option_t lcp_option_list[] = {
94 static u_int lcp_echo_interval = LCP_ECHOINTERVAL;
95 static u_int lcp_echo_fails = LCP_MAXECHOFAILS;
98 static fsm lcp_fsm[NUM_PPP];
105 static u32_t lcp_echos_pending = 0;
106 static u32_t lcp_echo_number = 0;
107 static u32_t lcp_echo_timer_running = 0;
110 static u_char nak_buffer[PPP_MRU];
115 static void lcp_resetci (
fsm*);
116 static int lcp_cilen (
fsm*);
117 static void lcp_addci (
fsm*, u_char*,
int*);
118 static int lcp_ackci (
fsm*, u_char*,
int);
119 static int lcp_nakci (
fsm*, u_char*,
int);
120 static int lcp_rejci (
fsm*, u_char*,
int);
121 static int lcp_reqci (
fsm*, u_char*,
int*,
int);
122 static void lcp_up (
fsm*);
123 static void lcp_down (
fsm*);
124 static void lcp_starting (
fsm*);
125 static void lcp_finished (
fsm*);
126 static int lcp_extcode (
fsm*,
int, u_char, u_char*,
int);
127 static void lcp_rprotrej (
fsm*, u_char*,
int);
133 static void lcp_echo_lowerup (
int);
134 static void lcp_echo_lowerdown (
int);
135 static void LcpEchoTimeout (
void*);
136 static void lcp_received_echo_reply (
fsm*,
int, u_char*,
int);
137 static void LcpSendEchoRequest (
fsm*);
138 static void LcpLinkFailure (
fsm*);
139 static void LcpEchoCheck (
fsm*);
164 static void lcp_input (
int, u_char *,
int);
165 static void lcp_protrej (
int);
176 #if PPP_ADDITIONAL_CALLBACKS
182 #if PPP_ADDITIONAL_CALLBACKS
196 #define CILEN_SHORT 4
202 #define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
218 n = strtol(p, &endp, 16);
220 option_error(
"escape parameter contains invalid hex number '%s'", p);
224 if (n < 0 || n == 0x5E || n > 0xFF) {
225 option_error(
"can't escape character 0x%x", n);
229 while (*p ==
',' || *p ==
' ')
242 fsm *f = &lcp_fsm[unit];
256 wo->
mru = PPP_DEFMRU;
269 ao->
mru = PPP_MAXMRU;
285 memset(xmit_accm[unit], 0,
sizeof(xmit_accm[0]));
295 xmit_accm[unit][3]));
307 fsm *f = &lcp_fsm[unit];
329 fsm *f = &lcp_fsm[unit];
362 ppp_set_xaccm(unit, &xmit_accm[unit]);
363 ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0);
364 ppp_recv_config(unit, PPP_MRU, 0x00000000l,
367 lcp_allowoptions[unit].
asyncmap = (u_long)xmit_accm[unit][0]
375 xmit_accm[unit][0]));
395 lcp_input(
int unit, u_char *p,
int len)
397 fsm *f = &lcp_fsm[unit];
407 lcp_extcode(
fsm *f,
int code, u_char
id, u_char *inp,
int len)
413 lcp_rprotrej(f, inp, len);
427 lcp_received_echo_reply(f,
id, inp, len);
446 lcp_rprotrej(
fsm *f, u_char *inp,
int len)
449 struct protent *protp;
452 if (len < (
int)
sizeof (u_short)) {
459 LCPDEBUG(
LOG_INFO, (
"lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
473 for (i = 0; (protp = ppp_protocols[i]) !=
NULL; ++i) {
474 if (protp->protocol == prot && protp->enabled_flag) {
475 (*protp->protrej)(f->
unit);
488 lcp_protrej(
int unit)
522 lcp_gotoptions[f->
unit] = lcp_wantoptions[f->
unit];
536 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
537 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
538 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
539 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
540 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
541 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
546 return (LENCISHORT(go->
neg_mru && go->
mru != PPP_DEFMRU) +
562 lcp_addci(
fsm *f, u_char *ucp,
int *lenp)
565 u_char *start_ucp = ucp;
567 #define ADDCIVOID(opt, neg) \
569 LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \
571 PUTCHAR(CILEN_VOID, ucp); \
573 #define ADDCISHORT(opt, neg, val) \
575 LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \
577 PUTCHAR(CILEN_SHORT, ucp); \
578 PUTSHORT(val, ucp); \
580 #define ADDCICHAP(opt, neg, val, digest) \
582 LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \
584 PUTCHAR(CILEN_CHAP, ucp); \
585 PUTSHORT(val, ucp); \
586 PUTCHAR(digest, ucp); \
588 #define ADDCILONG(opt, neg, val) \
590 LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \
592 PUTCHAR(CILEN_LONG, ucp); \
595 #define ADDCILQR(opt, neg, val) \
597 LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \
599 PUTCHAR(CILEN_LQR, ucp); \
600 PUTSHORT(PPP_LQR, ucp); \
603 #define ADDCICHAR(opt, neg, val) \
605 LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
607 PUTCHAR(CILEN_CHAR, ucp); \
621 if (ucp - start_ucp != *lenp) {
637 lcp_ackci(
fsm *f, u_char *p,
int len)
640 u_char cilen, citype, cichar;
649 #define ACKCIVOID(opt, neg) \
651 if ((len -= CILEN_VOID) < 0) \
653 GETCHAR(citype, p); \
655 if (cilen != CILEN_VOID || citype != opt) \
658 #define ACKCISHORT(opt, neg, val) \
660 if ((len -= CILEN_SHORT) < 0) \
662 GETCHAR(citype, p); \
664 if (cilen != CILEN_SHORT || citype != opt) \
666 GETSHORT(cishort, p); \
667 if (cishort != val) \
670 #define ACKCICHAR(opt, neg, val) \
672 if ((len -= CILEN_CHAR) < 0) \
674 GETCHAR(citype, p); \
676 if (cilen != CILEN_CHAR || citype != opt) \
678 GETCHAR(cichar, p); \
682 #define ACKCICHAP(opt, neg, val, digest) \
684 if ((len -= CILEN_CHAP) < 0) \
686 GETCHAR(citype, p); \
688 if (cilen != CILEN_CHAP || citype != opt) \
690 GETSHORT(cishort, p); \
691 if (cishort != val) \
693 GETCHAR(cichar, p); \
694 if (cichar != digest) \
697 #define ACKCILONG(opt, neg, val) \
699 if ((len -= CILEN_LONG) < 0) \
701 GETCHAR(citype, p); \
703 if (cilen != CILEN_LONG || citype != opt) \
705 GETLONG(cilong, p); \
709 #define ACKCILQR(opt, neg, val) \
711 if ((len -= CILEN_LQR) < 0) \
713 GETCHAR(citype, p); \
715 if (cilen != CILEN_LQR || citype != opt) \
717 GETSHORT(cishort, p); \
718 if (cishort != PPP_LQR) \
720 GETLONG(cilong, p); \
759 lcp_nakci(
fsm *f, u_char *p,
int len)
763 u_char citype, cichar, *next;
771 BZERO(&no,
sizeof(no));
779 #define NAKCIVOID(opt, neg, code) \
781 len >= CILEN_VOID && \
782 p[1] == CILEN_VOID && \
785 INCPTR(CILEN_VOID, p); \
789 #define NAKCICHAP(opt, neg, code) \
791 len >= CILEN_CHAP && \
792 p[1] == CILEN_CHAP && \
796 GETSHORT(cishort, p); \
797 GETCHAR(cichar, p); \
801 #define NAKCICHAR(opt, neg, code) \
803 len >= CILEN_CHAR && \
804 p[1] == CILEN_CHAR && \
808 GETCHAR(cichar, p); \
812 #define NAKCISHORT(opt, neg, code) \
814 len >= CILEN_SHORT && \
815 p[1] == CILEN_SHORT && \
817 len -= CILEN_SHORT; \
819 GETSHORT(cishort, p); \
823 #define NAKCILONG(opt, neg, code) \
825 len >= CILEN_LONG && \
826 p[1] == CILEN_LONG && \
830 GETLONG(cilong, p); \
834 #define NAKCILQR(opt, neg, code) \
836 len >= CILEN_LQR && \
837 p[1] == CILEN_LQR && \
841 GETSHORT(cishort, p); \
842 GETLONG(cilong, p); \
855 NAKCISHORT(
CI_MRU, neg_mru,
856 if (cishort <= wo->mru || cishort < PPP_DEFMRU) {
867 try.asyncmap = go->
asyncmap | cilong;
877 && len >= CILEN_SHORT
878 && p[0] ==
CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
884 GETSHORT(cishort, p);
885 if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
896 }
else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
924 p += cilen - CILEN_SHORT;
934 if (cishort != PPP_LQR) {
937 try.lqr_period = cilong;
952 try.magicnumber =
magic();
962 try.neg_pcompression = 0;
965 try.neg_accompression = 0;
984 while (len > CILEN_VOID) {
987 if (cilen < CILEN_VOID || (len -= cilen) < 0) {
990 next = p + cilen - 2;
995 || no.
neg_mru || cilen != CILEN_SHORT) {
998 GETSHORT(cishort, p);
999 if (cishort < PPP_DEFMRU) {
1016 cilen != CILEN_LONG) {
1022 || cilen != CILEN_VOID) {
1028 || cilen != CILEN_VOID) {
1051 if (++
try.numloops >= lcp_loopbackfail) {
1079 lcp_rejci(
fsm *f, u_char *p,
int len)
1094 #define REJCIVOID(opt, neg) \
1096 len >= CILEN_VOID && \
1097 p[1] == CILEN_VOID && \
1099 len -= CILEN_VOID; \
1100 INCPTR(CILEN_VOID, p); \
1102 LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \
1104 #define REJCISHORT(opt, neg, val) \
1106 len >= CILEN_SHORT && \
1107 p[1] == CILEN_SHORT && \
1109 len -= CILEN_SHORT; \
1111 GETSHORT(cishort, p); \
1113 if (cishort != val) { \
1117 LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \
1119 #define REJCICHAP(opt, neg, val, digest) \
1121 len >= CILEN_CHAP && \
1122 p[1] == CILEN_CHAP && \
1124 len -= CILEN_CHAP; \
1126 GETSHORT(cishort, p); \
1127 GETCHAR(cichar, p); \
1129 if (cishort != val || cichar != digest) { \
1134 LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \
1136 #define REJCILONG(opt, neg, val) \
1138 len >= CILEN_LONG && \
1139 p[1] == CILEN_LONG && \
1141 len -= CILEN_LONG; \
1143 GETLONG(cilong, p); \
1145 if (cilong != val) { \
1149 LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \
1151 #define REJCILQR(opt, neg, val) \
1153 len >= CILEN_LQR && \
1154 p[1] == CILEN_LQR && \
1158 GETSHORT(cishort, p); \
1159 GETLONG(cilong, p); \
1161 if (cishort != PPP_LQR || cilong != val) { \
1165 LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \
1167 #define REJCICBCP(opt, neg, val) \
1169 len >= CILEN_CBCP && \
1170 p[1] == CILEN_CBCP && \
1172 len -= CILEN_CBCP; \
1174 GETCHAR(cichar, p); \
1176 if (cichar != val) { \
1180 LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \
1226 int reject_if_disagree)
1244 size_t traceNdx = 0;
1250 BZERO(ho,
sizeof(*ho));
1282 }
else if (cilen != CILEN_SHORT) {
1287 GETSHORT(cishort, p);
1294 if (cishort < PPP_MINMRU) {
1298 PUTCHAR(CILEN_SHORT, nakp);
1299 PUTSHORT(PPP_MINMRU, nakp);
1305 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" MRU %d", cishort);
1306 traceNdx = strlen(traceBuf);
1315 }
else if (cilen != CILEN_LONG) {
1326 if ((ao->
asyncmap & ~cilong) != 0) {
1331 PUTCHAR(CILEN_LONG, nakp);
1332 PUTLONG(ao->
asyncmap | cilong, nakp);
1338 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" ASYNCMAP=%lX", cilong);
1339 traceNdx = strlen(traceBuf);
1344 if (cilen < CILEN_SHORT) {
1356 GETSHORT(cishort, p);
1369 if (cishort == PPP_PAP) {
1374 }
else if (cilen != CILEN_SHORT) {
1383 PUTCHAR(CILEN_CHAP, nakp);
1384 PUTSHORT(PPP_CHAP, nakp);
1390 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" PAP (%X)", cishort);
1391 traceNdx = strlen(traceBuf);
1395 if (cishort == PPP_CHAP) {
1400 }
else if (cilen != CILEN_CHAP) {
1409 PUTCHAR(CILEN_SHORT, nakp);
1410 PUTSHORT(PPP_PAP, nakp);
1422 PUTCHAR(CILEN_CHAP, nakp);
1423 PUTSHORT(PPP_CHAP, nakp);
1428 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" CHAP %X,%d", cishort, (
int)cichar);
1429 traceNdx = strlen(traceBuf);
1445 PUTCHAR(CILEN_CHAP, nakp);
1446 PUTSHORT(PPP_CHAP, nakp);
1450 PUTCHAR(CILEN_SHORT, nakp);
1451 PUTSHORT(PPP_PAP, nakp);
1456 GETSHORT(cishort, p);
1459 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" QUALITY (%x %x)", cishort, (
unsigned int) cilong);
1460 traceNdx = strlen(traceBuf);
1464 cilen != CILEN_LQR) {
1473 if (cishort != PPP_LQR) {
1476 PUTCHAR(CILEN_LQR, nakp);
1477 PUTSHORT(PPP_LQR, nakp);
1485 cilen != CILEN_LONG) {
1491 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" MAGICNUMBER (%lX)", cilong);
1492 traceNdx = strlen(traceBuf);
1503 PUTCHAR(CILEN_LONG, nakp);
1504 PUTLONG(cilong, nakp);
1514 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" PCOMPRESSION");
1515 traceNdx = strlen(traceBuf);
1518 cilen != CILEN_VOID) {
1527 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" ACCOMPRESSION");
1528 traceNdx = strlen(traceBuf);
1531 cilen != CILEN_VOID) {
1540 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" CI_MRRU");
1541 traceNdx = strlen(traceBuf);
1548 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" CI_SSNHF");
1549 traceNdx = strlen(traceBuf);
1556 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" CI_EPDISC");
1557 traceNdx = strlen(traceBuf);
1564 snprintf(&traceBuf[traceNdx],
sizeof(traceBuf),
" unknown %d", citype);
1565 traceNdx = strlen(traceBuf);
1573 if (traceNdx >= 80 - 32) {
1584 if (reject_if_disagree
1597 BCOPY(cip, rejp, cilen);
1599 INCPTR(cilen, rejp);
1612 *lenp = (int)(next - inp);
1618 *lenp = (int)(nakp - nak_buffer);
1619 BCOPY(nak_buffer, inp, *lenp);
1622 *lenp = (int)(rejp - inp);
1676 lcp_echo_lowerup(f->
unit);
1692 lcp_echo_lowerdown(f->
unit);
1696 ppp_send_config(f->
unit, PPP_MRU, 0xffffffffl, 0, 0);
1697 ppp_recv_config(f->
unit, PPP_MRU,
1708 lcp_starting(
fsm *f)
1718 lcp_finished(
fsm *f)
1724 #if PPP_ADDITIONAL_CALLBACKS
1730 print_string(
char *p,
int len,
void (*printer) (
void *,
char *, ...),
void *arg)
1735 for (; len > 0; --len) {
1737 if (
' ' <= c && c <=
'~') {
1738 if (c ==
'\\' || c ==
'"') {
1741 printer(arg,
"%c", c);
1745 printer(arg,
"\\n");
1748 printer(arg,
"\\r");
1751 printer(arg,
"\\t");
1754 printer(arg,
"\\%.3o", c);
1765 static char *lcp_codenames[] = {
1766 "ConfReq",
"ConfAck",
"ConfNak",
"ConfRej",
1767 "TermReq",
"TermAck",
"CodeRej",
"ProtRej",
1768 "EchoReq",
"EchoRep",
"DiscReq"
1772 lcp_printpkt( u_char *p,
int plen,
void (*printer) (
void *,
char *, ...),
void *arg)
1774 int code, id, len, olen;
1775 u_char *pstart, *optend;
1786 if (len < HEADERLEN || len > plen) {
1790 if (code >= 1 && code <=
sizeof(lcp_codenames) /
sizeof(
char *)) {
1791 printer(arg,
" %s", lcp_codenames[code-1]);
1793 printer(arg,
" code=0x%x", code);
1795 printer(arg,
" id=0x%x",
id);
1807 if (olen < 2 || olen > len) {
1815 if (olen == CILEN_SHORT) {
1817 GETSHORT(cishort, p);
1818 printer(arg,
"mru %d", cishort);
1822 if (olen == CILEN_LONG) {
1825 printer(arg,
"asyncmap 0x%lx", cilong);
1829 if (olen >= CILEN_SHORT) {
1831 printer(arg,
"auth ");
1832 GETSHORT(cishort, p);
1835 printer(arg,
"pap");
1838 printer(arg,
"chap");
1841 printer(arg,
"0x%x", cishort);
1846 if (olen >= CILEN_SHORT) {
1848 printer(arg,
"quality ");
1849 GETSHORT(cishort, p);
1852 printer(arg,
"lqr");
1855 printer(arg,
"0x%x", cishort);
1860 if (olen >= CILEN_CHAR) {
1862 printer(arg,
"callback ");
1863 GETSHORT(cishort, p);
1866 printer(arg,
"CBCP");
1869 printer(arg,
"0x%x", cishort);
1874 if (olen == CILEN_LONG) {
1877 printer(arg,
"magic 0x%x", cilong);
1881 if (olen == CILEN_VOID) {
1883 printer(arg,
"pcomp");
1887 if (olen == CILEN_VOID) {
1889 printer(arg,
"accomp");
1893 while (p < optend) {
1895 printer(arg,
" %.2x", code);
1903 if (len > 0 && *p >=
' ' && *p < 0x7f) {
1905 print_string((
char*)p, len, printer, arg);
1916 printer(arg,
" magic=0x%x", cilong);
1924 for (; len > 0; --len) {
1926 printer(arg,
" %.2x", code);
1929 return (
int)(p - pstart);
1937 LcpLinkFailure (
fsm *f)
1940 LCPDEBUG(
LOG_INFO, (
"No response to %d echo-requests\n", lcp_echos_pending));
1950 LcpEchoCheck (
fsm *f)
1952 LcpSendEchoRequest (f);
1957 LWIP_ASSERT(
"lcp_echo_timer_running == 0", lcp_echo_timer_running == 0);
1959 TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
1960 lcp_echo_timer_running = 1;
1967 LcpEchoTimeout (
void *arg)
1969 if (lcp_echo_timer_running != 0) {
1970 lcp_echo_timer_running = 0;
1971 LcpEchoCheck ((
fsm *) arg);
1979 lcp_received_echo_reply (
fsm *f,
int id, u_char *inp,
int len)
1990 GETLONG(magic, inp);
1997 lcp_echos_pending = 0;
2004 LcpSendEchoRequest (
fsm *f)
2007 u_char pkt[4], *pktp;
2012 if (lcp_echo_fails != 0) {
2013 if (lcp_echos_pending >= lcp_echo_fails) {
2015 lcp_echos_pending = 0;
2025 PUTLONG(lcp_magic, pktp);
2026 fsm_sdata(f,
ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (
int)(pktp - pkt));
2027 ++lcp_echos_pending;
2036 lcp_echo_lowerup (
int unit)
2038 fsm *f = &lcp_fsm[unit];
2041 lcp_echos_pending = 0;
2042 lcp_echo_number = 0;
2043 lcp_echo_timer_running = 0;
2046 if (lcp_echo_interval != 0) {
2056 lcp_echo_lowerdown (
int unit)
2058 fsm *f = &lcp_fsm[unit];
2060 if (lcp_echo_timer_running != 0) {
2061 UNTIMEOUT (LcpEchoTimeout, f);
2062 lcp_echo_timer_running = 0;