43 #include "netif/ppp/ppp_opts.h" 56 #include "netif/ppp/ppp_impl.h" 58 #include "netif/ppp/fsm.h" 59 #include "netif/ppp/lcp.h" 61 #include "netif/ppp/chap-new.h" 63 #include "netif/ppp/magic.h" 71 #define DELAYED_UP 0x80 73 static void lcp_delayed_up(
void *arg);
79 int lcp_echo_interval = 0;
80 int lcp_echo_fails = 0;
85 static u_int lcp_echo_interval = LCP_ECHOINTERVAL;
86 static u_int lcp_echo_fails = LCP_MAXECHOFAILS;
91 bool lcp_echo_adaptive = 0;
98 static int noopt (
char **);
101 #ifdef HAVE_MULTILINK 102 static int setendpoint (
char **);
103 static void printendpoint (option_t *,
void (*)(
void *,
char *, ...),
108 static option_t lcp_option_list[] = {
110 {
"-all", o_special_noarg, (
void *)noopt,
111 "Don't request/allow any LCP options" },
113 {
"noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
114 "Disable address/control compression",
115 OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
116 {
"-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
117 "Disable address/control compression",
118 OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
120 {
"asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
121 "Set asyncmap (for received packets)",
122 OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
123 {
"-as", o_uint32, &lcp_wantoptions[0].asyncmap,
124 "Set asyncmap (for received packets)",
125 OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
126 {
"default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
127 "Disable asyncmap negotiation",
128 OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
129 &lcp_allowoptions[0].neg_asyncmap },
130 {
"-am", o_uint32, &lcp_wantoptions[0].asyncmap,
131 "Disable asyncmap negotiation",
132 OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
133 &lcp_allowoptions[0].neg_asyncmap },
135 {
"nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
136 "Disable magic number negotiation (looped-back line detection)",
137 OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
138 {
"-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
139 "Disable magic number negotiation (looped-back line detection)",
140 OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
142 {
"mru", o_int, &lcp_wantoptions[0].mru,
143 "Set MRU (maximum received packet size) for negotiation",
144 OPT_PRIO, &lcp_wantoptions[0].neg_mru },
145 {
"default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
146 "Disable MRU negotiation (use default 1500)",
147 OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
148 {
"-mru", o_bool, &lcp_wantoptions[0].neg_mru,
149 "Disable MRU negotiation (use default 1500)",
150 OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
152 {
"mtu", o_int, &lcp_allowoptions[0].mru,
153 "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
155 {
"nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
156 "Disable protocol field compression",
157 OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
158 {
"-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
159 "Disable protocol field compression",
160 OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
162 {
"passive", o_bool, &lcp_wantoptions[0].passive,
163 "Set passive mode", 1 },
164 {
"-p", o_bool, &lcp_wantoptions[0].passive,
165 "Set passive mode", OPT_ALIAS | 1 },
167 {
"silent", o_bool, &lcp_wantoptions[0].silent,
168 "Set silent mode", 1 },
170 {
"lcp-echo-failure", o_int, &lcp_echo_fails,
171 "Set number of consecutive echo failures to indicate link failure",
173 {
"lcp-echo-interval", o_int, &lcp_echo_interval,
174 "Set time in seconds between LCP echo requests", OPT_PRIO },
176 {
"lcp-echo-adaptive", o_bool, &lcp_echo_adaptive,
177 "Suppress LCP echo requests if traffic was received", 1 },
179 {
"lcp-restart", o_int, &lcp_fsm[0].timeouttime,
180 "Set time in seconds between LCP retransmissions", OPT_PRIO },
181 {
"lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
182 "Set maximum number of LCP terminate-request transmissions", OPT_PRIO },
183 {
"lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
184 "Set maximum number of LCP configure-request transmissions", OPT_PRIO },
185 {
"lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
186 "Set limit on number of LCP configure-naks", OPT_PRIO },
188 {
"receive-all", o_bool, &lax_recv,
189 "Accept all received control characters", 1 },
191 #ifdef HAVE_MULTILINK 192 {
"mrru", o_int, &lcp_wantoptions[0].mrru,
193 "Maximum received packet size for multilink bundle",
194 OPT_PRIO, &lcp_wantoptions[0].neg_mrru },
196 {
"mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
197 "Use short sequence numbers in multilink headers",
198 OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf },
199 {
"nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
200 "Don't use short sequence numbers in multilink headers",
201 OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf },
203 {
"endpoint", o_special, (
void *) setendpoint,
204 "Endpoint discriminator for multilink",
205 OPT_PRIO | OPT_A2PRINTER, (
void *) printendpoint },
208 {
"noendpoint", o_bool, &noendpoint,
209 "Don't send or accept multilink endpoint discriminator", 1 },
218 static void lcp_resetci(fsm *f);
219 static int lcp_cilen(fsm *f);
220 static void lcp_addci(fsm *f, u_char *ucp,
int *lenp);
221 static int lcp_ackci(fsm *f, u_char *p,
int len);
222 static int lcp_nakci(fsm *f, u_char *p,
int len,
int treat_as_reject);
223 static int lcp_rejci(fsm *f, u_char *p,
int len);
224 static int lcp_reqci(fsm *f, u_char *inp,
int *lenp,
int reject_if_disagree);
225 static void lcp_up(fsm *f);
226 static void lcp_down(fsm *f);
227 static void lcp_starting (fsm *);
228 static void lcp_finished (fsm *);
229 static int lcp_extcode(fsm *f,
int code,
int id, u_char *inp,
int len);
230 static void lcp_rprotrej(fsm *f, u_char *inp,
int len);
236 static void lcp_echo_lowerup(ppp_pcb *pcb);
237 static void lcp_echo_lowerdown(ppp_pcb *pcb);
238 static void LcpEchoTimeout(
void *arg);
239 static void lcp_received_echo_reply(fsm *f,
int id, u_char *inp,
int len);
240 static void LcpSendEchoRequest(fsm *f);
241 static void LcpLinkFailure(fsm *f);
242 static void LcpEchoCheck(fsm *f);
244 static const fsm_callbacks lcp_callbacks = {
267 static void lcp_init(ppp_pcb *pcb);
268 static void lcp_input(ppp_pcb *pcb, u_char *p,
int len);
269 static void lcp_protrej(ppp_pcb *pcb);
271 static int lcp_printpkt(
const u_char *p,
int plen,
272 void (*printer) (
void *,
const char *, ...),
void *arg);
275 const struct protent lcp_protent = {
309 #define CILEN_SHORT 4 319 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ 320 (x) == CONFNAK ? "NAK" : "REJ") 330 BZERO((
char *) &lcp_wantoptions[0],
sizeof (
struct lcp_options));
331 BZERO((
char *) &lcp_allowoptions[0],
sizeof (
struct lcp_options));
337 #ifdef HAVE_MULTILINK 342 if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
343 lcp_wantoptions[0].neg_endpoint = 1;
346 option_error(
"Can't parse '%s' as an endpoint discriminator", *argv);
351 printendpoint(opt, printer, arg)
353 void (*printer) (
void *,
char *, ...);
356 printer(arg,
"%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));
363 static void lcp_init(ppp_pcb *pcb) {
364 fsm *f = &pcb->lcp_fsm;
365 lcp_options *wo = &pcb->lcp_wantoptions;
366 lcp_options *ao = &pcb->lcp_allowoptions;
369 f->protocol = PPP_LCP;
370 f->callbacks = &lcp_callbacks;
374 BZERO(wo,
sizeof(*wo));
376 wo->mru = PPP_DEFMRU;
377 wo->neg_asyncmap = 1;
378 wo->neg_magicnumber = 1;
379 wo->neg_pcompression = 1;
380 wo->neg_accompression = 1;
382 BZERO(ao,
sizeof(*ao));
384 ao->mru = PPP_MAXMRU;
385 ao->neg_asyncmap = 1;
388 ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED;
396 ao->neg_magicnumber = 1;
397 ao->neg_pcompression = 1;
398 ao->neg_accompression = 1;
399 ao->neg_endpoint = 1;
406 void lcp_open(ppp_pcb *pcb) {
407 fsm *f = &pcb->lcp_fsm;
408 lcp_options *wo = &pcb->lcp_wantoptions;
410 f->flags &= ~(OPT_PASSIVE | OPT_SILENT);
412 f->flags |= OPT_PASSIVE;
414 f->flags |= OPT_SILENT;
422 void lcp_close(ppp_pcb *pcb,
const char *reason) {
423 fsm *f = &pcb->lcp_fsm;
426 if (pcb->phase != PPP_PHASE_DEAD
427 #ifdef HAVE_MULTILINK
428 && pcb->phase != PPP_PHASE_MASTER
431 new_phase(pcb, PPP_PHASE_TERMINATE);
433 if (f->flags & DELAYED_UP) {
434 UNTIMEOUT(lcp_delayed_up, f);
435 f->state = PPP_FSM_STOPPED;
439 fsm_close(f, reason);
440 if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) {
448 f->flags &= ~DELAYED_UP;
457 void lcp_lowerup(ppp_pcb *pcb) {
458 lcp_options *wo = &pcb->lcp_wantoptions;
459 fsm *f = &pcb->lcp_fsm;
465 if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0
466 || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff),
467 wo->neg_pcompression, wo->neg_accompression) < 0)
469 pcb->peer_mru = PPP_MRU;
471 if (pcb->settings.listen_time != 0) {
472 f->flags |= DELAYED_UP;
473 TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time);
482 void lcp_lowerdown(ppp_pcb *pcb) {
483 fsm *f = &pcb->lcp_fsm;
485 if (f->flags & DELAYED_UP) {
486 f->flags &= ~DELAYED_UP;
487 UNTIMEOUT(lcp_delayed_up, f);
496 static void lcp_delayed_up(
void *arg) {
499 if (f->flags & DELAYED_UP) {
500 f->flags &= ~DELAYED_UP;
509 static void lcp_input(ppp_pcb *pcb, u_char *p,
int len) {
510 fsm *f = &pcb->lcp_fsm;
512 if (f->flags & DELAYED_UP) {
513 f->flags &= ~DELAYED_UP;
514 UNTIMEOUT(lcp_delayed_up, f);
517 fsm_input(f, p, len);
523 static int lcp_extcode(fsm *f,
int code,
int id, u_char *inp,
int len) {
524 ppp_pcb *pcb = f->pcb;
525 lcp_options *go = &pcb->lcp_gotoptions;
530 lcp_rprotrej(f, inp, len);
534 if (f->state != PPP_FSM_OPENED)
537 PUTLONG(go->magicnumber, magp);
538 fsm_sdata(f, ECHOREP,
id, inp, len);
542 lcp_received_echo_reply(f,
id, inp, len);
562 static void lcp_rprotrej(fsm *f, u_char *inp,
int len) {
564 const struct protent *protp;
571 LCPDEBUG((
"lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
581 if( f->state != PPP_FSM_OPENED ){
582 LCPDEBUG((
"Protocol-Reject discarded: LCP in state %d", f->state));
587 pname = protocol_name(prot);
593 for (i = 0; (protp = protocols[i]) != NULL; ++i)
594 if (protp->protocol == prot) {
597 ppp_dbglog(
"Protocol-Reject for '%s' (0x%x) received", pname,
601 ppp_dbglog(
"Protocol-Reject for 0x%x received", prot);
602 (*protp->protrej)(f->pcb);
608 ppp_warn(
"Protocol-Reject for unsupported protocol '%s' (0x%x)", pname,
612 ppp_warn(
"Protocol-Reject for unsupported protocol 0x%x", prot);
620 static void lcp_protrej(ppp_pcb *pcb) {
624 ppp_error(
"Received Protocol-Reject for LCP!");
625 fsm_protreject(&pcb->lcp_fsm);
632 void lcp_sprotrej(ppp_pcb *pcb, u_char *p,
int len) {
633 fsm *f = &pcb->lcp_fsm;
643 fsm_sdata(f, PROTREJ, ++f->id,
651 static void lcp_resetci(fsm *f) {
652 ppp_pcb *pcb = f->pcb;
653 lcp_options *wo = &pcb->lcp_wantoptions;
654 lcp_options *go = &pcb->lcp_gotoptions;
655 lcp_options *ao = &pcb->lcp_allowoptions;
660 if (pcb->settings.user && pcb->settings.passwd) {
662 if (pcb->settings.refuse_pap) {
667 if (pcb->settings.refuse_chap) {
668 ao->chap_mdtype &= ~MDTYPE_MD5;
671 if (pcb->settings.refuse_mschap) {
672 ao->chap_mdtype &= ~MDTYPE_MICROSOFT;
674 if (pcb->settings.refuse_mschap_v2) {
675 ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2;
678 ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE);
681 if (pcb->settings.refuse_eap) {
688 if (pcb->settings.auth_required) {
690 if (!pcb->settings.refuse_pap) {
695 if (!pcb->settings.refuse_chap) {
696 wo->chap_mdtype |= MDTYPE_MD5;
699 if (!pcb->settings.refuse_mschap) {
700 wo->chap_mdtype |= MDTYPE_MICROSOFT;
702 if (!pcb->settings.refuse_mschap_v2) {
703 wo->chap_mdtype |= MDTYPE_MICROSOFT_V2;
706 wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE);
709 if (!pcb->settings.refuse_eap) {
722 ao->chap_mdtype = MDTYPE_NONE;
729 PPPDEBUG(LOG_DEBUG, (
"ppp: auth protocols:"));
731 PPPDEBUG(LOG_DEBUG, (
" PAP=%d", ao->neg_upap));
734 PPPDEBUG(LOG_DEBUG, (
" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5)));
736 PPPDEBUG(LOG_DEBUG, (
" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2)));
740 PPPDEBUG(LOG_DEBUG, (
" EAP=%d", ao->neg_eap));
742 PPPDEBUG(LOG_DEBUG, (
"\n"));
746 wo->magicnumber = magic();
749 #ifdef HAVE_MULTILINK 754 go->neg_endpoint = 0;
755 #ifdef HAVE_MULTILINK 758 if (pcb->settings.noendpoint)
759 ao->neg_endpoint = 0;
760 pcb->peer_mru = PPP_MRU;
770 static int lcp_cilen(fsm *f) {
771 ppp_pcb *pcb = f->pcb;
772 lcp_options *go = &pcb->lcp_gotoptions;
774 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) 776 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) 778 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) 779 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) 781 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) 783 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) 789 return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) +
790 LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
792 LENCISHORT(go->neg_eap) +
796 LENCICHAP(!go->neg_eap && go->neg_chap) +
799 LENCICHAP(go->neg_chap) +
803 #
if EAP_SUPPORT && CHAP_SUPPORT
804 LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) +
806 #
if EAP_SUPPORT && !CHAP_SUPPORT
807 LENCISHORT(!go->neg_eap && go->neg_upap) +
809 #
if !EAP_SUPPORT && CHAP_SUPPORT
810 LENCISHORT(!go->neg_chap && go->neg_upap) +
812 #
if !EAP_SUPPORT && !CHAP_SUPPORT
813 LENCISHORT(go->neg_upap) +
817 LENCILQR(go->neg_lqr) +
819 LENCICBCP(go->neg_cbcp) +
820 LENCILONG(go->neg_magicnumber) +
821 LENCIVOID(go->neg_pcompression) +
822 LENCIVOID(go->neg_accompression) +
823 #ifdef HAVE_MULTILINK
824 LENCISHORT(go->neg_mrru) +
826 LENCIVOID(go->neg_ssnhf) +
827 (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
834 static void lcp_addci(fsm *f, u_char *ucp,
int *lenp) {
835 ppp_pcb *pcb = f->pcb;
836 lcp_options *go = &pcb->lcp_gotoptions;
837 u_char *start_ucp = ucp;
839 #define ADDCIVOID(opt, neg) \ 842 PUTCHAR(CILEN_VOID, ucp); \ 844 #define ADDCISHORT(opt, neg, val) \ 847 PUTCHAR(CILEN_SHORT, ucp); \ 848 PUTSHORT(val, ucp); \ 851 #define ADDCICHAP(opt, neg, val) \ 853 PUTCHAR((opt), ucp); \ 854 PUTCHAR(CILEN_CHAP, ucp); \ 855 PUTSHORT(PPP_CHAP, ucp); \ 856 PUTCHAR((CHAP_DIGEST(val)), ucp); \ 859 #define ADDCILONG(opt, neg, val) \ 862 PUTCHAR(CILEN_LONG, ucp); \ 866 #define ADDCILQR(opt, neg, val) \ 869 PUTCHAR(CILEN_LQR, ucp); \ 870 PUTSHORT(PPP_LQR, ucp); \ 874 #define ADDCICHAR(opt, neg, val) \ 877 PUTCHAR(CILEN_CHAR, ucp); \ 880 #define ADDCIENDP(opt, neg, class, val, len) \ 884 PUTCHAR(CILEN_CHAR + len, ucp); \ 885 PUTCHAR(class, ucp); \ 886 for (i = 0; i < len; ++i) \ 887 PUTCHAR(val[i], ucp); \ 890 ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
891 ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
894 ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
898 ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
901 ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
905 #if EAP_SUPPORT && CHAP_SUPPORT 906 ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP);
908 #if EAP_SUPPORT && !CHAP_SUPPORT 909 ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP);
911 #if !EAP_SUPPORT && CHAP_SUPPORT 912 ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
914 #if !EAP_SUPPORT && !CHAP_SUPPORT 915 ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP);
919 ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
921 ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
922 ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
923 ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
924 ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
925 #ifdef HAVE_MULTILINK 926 ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
928 ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
929 ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_,
930 go->endpoint.value, go->endpoint.length);
932 if (ucp - start_ucp != *lenp) {
934 ppp_error(
"Bug in lcp_addci: wrong length");
947 static int lcp_ackci(fsm *f, u_char *p,
int len) {
948 ppp_pcb *pcb = f->pcb;
949 lcp_options *go = &pcb->lcp_gotoptions;
950 u_char cilen, citype, cichar;
959 #define ACKCIVOID(opt, neg) \ 961 if ((len -= CILEN_VOID) < 0) \ 963 GETCHAR(citype, p); \ 965 if (cilen != CILEN_VOID || \ 969 #define ACKCISHORT(opt, neg, val) \ 971 if ((len -= CILEN_SHORT) < 0) \ 973 GETCHAR(citype, p); \ 975 if (cilen != CILEN_SHORT || \ 978 GETSHORT(cishort, p); \ 979 if (cishort != val) \ 982 #define ACKCICHAR(opt, neg, val) \ 984 if ((len -= CILEN_CHAR) < 0) \ 986 GETCHAR(citype, p); \ 988 if (cilen != CILEN_CHAR || \ 991 GETCHAR(cichar, p); \ 996 #define ACKCICHAP(opt, neg, val) \ 998 if ((len -= CILEN_CHAP) < 0) \ 1000 GETCHAR(citype, p); \ 1001 GETCHAR(cilen, p); \ 1002 if (cilen != CILEN_CHAP || \ 1005 GETSHORT(cishort, p); \ 1006 if (cishort != PPP_CHAP) \ 1008 GETCHAR(cichar, p); \ 1009 if (cichar != (CHAP_DIGEST(val))) \ 1013 #define ACKCILONG(opt, neg, val) \ 1015 if ((len -= CILEN_LONG) < 0) \ 1017 GETCHAR(citype, p); \ 1018 GETCHAR(cilen, p); \ 1019 if (cilen != CILEN_LONG || \ 1022 GETLONG(cilong, p); \ 1023 if (cilong != val) \ 1027 #define ACKCILQR(opt, neg, val) \ 1029 if ((len -= CILEN_LQR) < 0) \ 1031 GETCHAR(citype, p); \ 1032 GETCHAR(cilen, p); \ 1033 if (cilen != CILEN_LQR || \ 1036 GETSHORT(cishort, p); \ 1037 if (cishort != PPP_LQR) \ 1039 GETLONG(cilong, p); \ 1040 if (cilong != val) \ 1044 #define ACKCIENDP(opt, neg, class, val, vlen) \ 1047 if ((len -= CILEN_CHAR + vlen) < 0) \ 1049 GETCHAR(citype, p); \ 1050 GETCHAR(cilen, p); \ 1051 if (cilen != CILEN_CHAR + vlen || \ 1054 GETCHAR(cichar, p); \ 1055 if (cichar != class) \ 1057 for (i = 0; i < vlen; ++i) { \ 1058 GETCHAR(cichar, p); \ 1059 if (cichar != val[i]) \ 1064 ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
1065 ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
1068 ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
1072 ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
1075 ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
1079 #if EAP_SUPPORT && CHAP_SUPPORT 1080 ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP);
1082 #if EAP_SUPPORT && !CHAP_SUPPORT 1083 ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP);
1085 #if !EAP_SUPPORT && CHAP_SUPPORT 1086 ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
1088 #if !EAP_SUPPORT && !CHAP_SUPPORT 1089 ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP);
1093 ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1095 ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
1096 ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
1097 ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
1098 ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
1099 #ifdef HAVE_MULTILINK 1100 ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
1102 ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
1103 ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_,
1104 go->endpoint.value, go->endpoint.length);
1113 LCPDEBUG((
"lcp_acki: received bad Ack!"));
1127 static int lcp_nakci(fsm *f, u_char *p,
int len,
int treat_as_reject) {
1128 ppp_pcb *pcb = f->pcb;
1129 lcp_options *go = &pcb->lcp_gotoptions;
1130 lcp_options *wo = &pcb->lcp_wantoptions;
1131 u_char citype, cichar, *next;
1136 int looped_back = 0;
1139 BZERO(&no,
sizeof(no));
1147 #define NAKCIVOID(opt, neg) \ 1149 len >= CILEN_VOID && \ 1150 p[1] == CILEN_VOID && \ 1152 len -= CILEN_VOID; \ 1153 INCPTR(CILEN_VOID, p); \ 1158 #define NAKCICHAP(opt, neg, code) \ 1160 len >= CILEN_CHAP && \ 1161 p[1] == CILEN_CHAP && \ 1163 len -= CILEN_CHAP; \ 1165 GETSHORT(cishort, p); \ 1166 GETCHAR(cichar, p); \ 1171 #define NAKCICHAR(opt, neg, code) \ 1173 len >= CILEN_CHAR && \ 1174 p[1] == CILEN_CHAR && \ 1176 len -= CILEN_CHAR; \ 1178 GETCHAR(cichar, p); \ 1182 #define NAKCISHORT(opt, neg, code) \ 1184 len >= CILEN_SHORT && \ 1185 p[1] == CILEN_SHORT && \ 1187 len -= CILEN_SHORT; \ 1189 GETSHORT(cishort, p); \ 1193 #define NAKCILONG(opt, neg, code) \ 1195 len >= CILEN_LONG && \ 1196 p[1] == CILEN_LONG && \ 1198 len -= CILEN_LONG; \ 1200 GETLONG(cilong, p); \ 1205 #define NAKCILQR(opt, neg, code) \ 1207 len >= CILEN_LQR && \ 1208 p[1] == CILEN_LQR && \ 1212 GETSHORT(cishort, p); \ 1213 GETLONG(cilong, p); \ 1218 #define NAKCIENDP(opt, neg) \ 1220 len >= CILEN_CHAR && \ 1222 p[1] >= CILEN_CHAR && \ 1241 if (go->neg_mru && go->mru != PPP_DEFMRU) {
1242 NAKCISHORT(CI_MRU, neg_mru,
1243 if (cishort <= wo->mru || cishort <= PPP_DEFMRU)
1251 if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
1252 NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
1253 try_.asyncmap = go->asyncmap | cilong;
1273 && len >= CILEN_SHORT
1274 && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
1278 no.neg_chap = go->neg_chap;
1281 no.neg_upap = go->neg_upap;
1284 no.neg_eap = go->neg_eap;
1287 GETSHORT(cishort, p);
1290 if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
1314 if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
1321 if (CHAP_CANDIGEST(go->chap_mdtype, cichar))
1322 try_.chap_mdtype = CHAP_MDTYPE_D(cichar);
1330 if (cichar != CHAP_DIGEST(go->chap_mdtype)) {
1331 if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) {
1333 try_.chap_mdtype = CHAP_MDTYPE_D(cichar);
1336 try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype));
1337 if (try_.chap_mdtype == MDTYPE_NONE)
1365 if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap)
1366 ppp_dbglog(
"Unexpected Conf-Nak for EAP");
1390 p += cilen - CILEN_SHORT;
1400 NAKCILQR(CI_QUALITY, neg_lqr,
1401 if (cishort != PPP_LQR)
1404 try_.lqr_period = cilong;
1411 NAKCICHAR(CI_CALLBACK, neg_cbcp,
1419 NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1420 try_.magicnumber = magic();
1429 NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1430 NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1432 #ifdef HAVE_MULTILINK 1438 NAKCISHORT(CI_MRRU, neg_mrru,
1439 if (treat_as_reject)
1441 else if (cishort <= wo->mrru)
1442 try_.mrru = cishort;
1453 NAKCIVOID(CI_SSNHF, neg_ssnhf);
1459 NAKCIENDP(CI_EPDISC, neg_endpoint);
1477 while (len >= CILEN_VOID) {
1480 if (cilen < CILEN_VOID || (len -= cilen) < 0)
1482 next = p + cilen - 2;
1486 if ((go->neg_mru && go->mru != PPP_DEFMRU)
1487 || no.neg_mru || cilen != CILEN_SHORT)
1489 GETSHORT(cishort, p);
1490 if (cishort < PPP_DEFMRU) {
1496 if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1497 || no.neg_asyncmap || cilen != CILEN_LONG)
1503 || go->neg_chap || no.neg_chap
1506 || go->neg_upap || no.neg_upap
1509 || go->neg_eap || no.neg_eap
1514 case CI_MAGICNUMBER:
1515 if (go->neg_magicnumber || no.neg_magicnumber ||
1516 cilen != CILEN_LONG)
1519 case CI_PCOMPRESSION:
1520 if (go->neg_pcompression || no.neg_pcompression
1521 || cilen != CILEN_VOID)
1524 case CI_ACCOMPRESSION:
1525 if (go->neg_accompression || no.neg_accompression
1526 || cilen != CILEN_VOID)
1531 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1535 #ifdef HAVE_MULTILINK 1537 if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1542 if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1547 if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1560 if (f->state != PPP_FSM_OPENED) {
1562 if (++try_.numloops >= pcb->settings.lcp_loopbackfail) {
1563 ppp_notice(
"Serial line is looped back.");
1564 pcb->err_code = PPPERR_LOOPBACK;
1565 lcp_close(f->pcb,
"Loopback detected");
1575 LCPDEBUG((
"lcp_nakci: received bad Nak!"));
1589 static int lcp_rejci(fsm *f, u_char *p,
int len) {
1590 ppp_pcb *pcb = f->pcb;
1591 lcp_options *go = &pcb->lcp_gotoptions;
1604 #define REJCIVOID(opt, neg) \ 1606 len >= CILEN_VOID && \ 1607 p[1] == CILEN_VOID && \ 1609 len -= CILEN_VOID; \ 1610 INCPTR(CILEN_VOID, p); \ 1613 #define REJCISHORT(opt, neg, val) \ 1615 len >= CILEN_SHORT && \ 1616 p[1] == CILEN_SHORT && \ 1618 len -= CILEN_SHORT; \ 1620 GETSHORT(cishort, p); \ 1622 if (cishort != val) \ 1627 #if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT 1628 #define REJCICHAP(opt, neg, val) \ 1630 len >= CILEN_CHAP && \ 1631 p[1] == CILEN_CHAP && \ 1633 len -= CILEN_CHAP; \ 1635 GETSHORT(cishort, p); \ 1636 GETCHAR(cichar, p); \ 1638 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1641 try_.neg_eap = try_.neg_upap = 0; \ 1645 #if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT 1646 #define REJCICHAP(opt, neg, val) \ 1648 len >= CILEN_CHAP && \ 1649 p[1] == CILEN_CHAP && \ 1651 len -= CILEN_CHAP; \ 1653 GETSHORT(cishort, p); \ 1654 GETCHAR(cichar, p); \ 1656 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1659 try_.neg_upap = 0; \ 1663 #if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT 1664 #define REJCICHAP(opt, neg, val) \ 1666 len >= CILEN_CHAP && \ 1667 p[1] == CILEN_CHAP && \ 1669 len -= CILEN_CHAP; \ 1671 GETSHORT(cishort, p); \ 1672 GETCHAR(cichar, p); \ 1674 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1681 #if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT 1682 #define REJCICHAP(opt, neg, val) \ 1684 len >= CILEN_CHAP && \ 1685 p[1] == CILEN_CHAP && \ 1687 len -= CILEN_CHAP; \ 1689 GETSHORT(cishort, p); \ 1690 GETCHAR(cichar, p); \ 1692 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1698 #define REJCILONG(opt, neg, val) \ 1700 len >= CILEN_LONG && \ 1701 p[1] == CILEN_LONG && \ 1703 len -= CILEN_LONG; \ 1705 GETLONG(cilong, p); \ 1707 if (cilong != val) \ 1712 #define REJCILQR(opt, neg, val) \ 1714 len >= CILEN_LQR && \ 1715 p[1] == CILEN_LQR && \ 1719 GETSHORT(cishort, p); \ 1720 GETLONG(cilong, p); \ 1722 if (cishort != PPP_LQR || cilong != val) \ 1727 #define REJCICBCP(opt, neg, val) \ 1729 len >= CILEN_CBCP && \ 1730 p[1] == CILEN_CBCP && \ 1732 len -= CILEN_CBCP; \ 1734 GETCHAR(cichar, p); \ 1736 if (cichar != val) \ 1740 #define REJCIENDP(opt, neg, class, val, vlen) \ 1742 len >= CILEN_CHAR + vlen && \ 1744 p[1] == CILEN_CHAR + vlen) { \ 1746 len -= CILEN_CHAR + vlen; \ 1748 GETCHAR(cichar, p); \ 1749 if (cichar != class) \ 1751 for (i = 0; i < vlen; ++i) { \ 1752 GETCHAR(cichar, p); \ 1753 if (cichar != val[i]) \ 1759 REJCISHORT(CI_MRU, neg_mru, go->mru);
1760 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1762 REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
1766 REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
1767 if (!go->neg_chap) {
1770 REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1779 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1781 REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1782 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1783 REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1784 REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1785 #ifdef HAVE_MULTILINK 1786 REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1788 REJCIVOID(CI_SSNHF, neg_ssnhf);
1789 REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_,
1790 go->endpoint.value, go->endpoint.length);
1800 if (f->state != PPP_FSM_OPENED)
1805 LCPDEBUG((
"lcp_rejci: received bad Reject!"));
1820 static int lcp_reqci(fsm *f, u_char *inp,
int *lenp,
int reject_if_disagree) {
1821 ppp_pcb *pcb = f->pcb;
1822 lcp_options *go = &pcb->lcp_gotoptions;
1823 lcp_options *ho = &pcb->lcp_hisoptions;
1824 lcp_options *ao = &pcb->lcp_allowoptions;
1826 int cilen, citype, cichar;
1840 BZERO(ho,
sizeof(*ho));
1854 nakoutp = (u_char*)nakp->
payload;
1862 LCPDEBUG((
"lcp_reqci: bad CI length!"));
1877 cilen != CILEN_SHORT) {
1881 GETSHORT(cishort, p);
1888 if (cishort < PPP_MINMRU) {
1890 PUTCHAR(CI_MRU, nakoutp);
1891 PUTCHAR(CILEN_SHORT, nakoutp);
1892 PUTSHORT(PPP_MINMRU, nakoutp);
1900 if (!ao->neg_asyncmap ||
1901 cilen != CILEN_LONG) {
1911 if ((ao->asyncmap & ~cilong) != 0) {
1913 PUTCHAR(CI_ASYNCMAP, nakoutp);
1914 PUTCHAR(CILEN_LONG, nakoutp);
1915 PUTLONG(ao->asyncmap | cilong, nakoutp);
1918 ho->neg_asyncmap = 1;
1919 ho->asyncmap = cilong;
1923 if (cilen < CILEN_SHORT ||
1938 ppp_dbglog(
"No auth is possible");
1942 GETSHORT(cishort, p);
1956 if (cishort == PPP_PAP) {
1965 || cilen != CILEN_SHORT) {
1966 LCPDEBUG((
"lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1970 if (!ao->neg_upap) {
1972 PUTCHAR(CI_AUTHTYPE, nakoutp);
1975 PUTCHAR(CILEN_SHORT, nakoutp);
1976 PUTSHORT(PPP_EAP, nakoutp);
1980 PUTCHAR(CILEN_CHAP, nakoutp);
1981 PUTSHORT(PPP_CHAP, nakoutp);
1982 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
1994 if (cishort == PPP_CHAP) {
2003 cilen != CILEN_CHAP) {
2004 LCPDEBUG((
"lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
2008 if (!ao->neg_chap) {
2010 PUTCHAR(CI_AUTHTYPE, nakoutp);
2011 PUTCHAR(CILEN_SHORT, nakoutp);
2014 PUTSHORT(PPP_EAP, nakoutp);
2019 PUTSHORT(PPP_PAP, nakoutp);
2027 if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) {
2033 PUTCHAR(CI_AUTHTYPE, nakoutp);
2034 PUTCHAR(CILEN_CHAP, nakoutp);
2035 PUTSHORT(PPP_CHAP, nakoutp);
2036 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2039 ho->chap_mdtype = CHAP_MDTYPE_D(cichar);
2045 if (cishort == PPP_EAP) {
2054 cilen != CILEN_SHORT) {
2055 LCPDEBUG((
"lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
2061 PUTCHAR(CI_AUTHTYPE, nakoutp);
2064 PUTCHAR(CILEN_CHAP, nakoutp);
2065 PUTSHORT(PPP_CHAP, nakoutp);
2066 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2071 PUTCHAR(CILEN_SHORT, nakoutp);
2072 PUTSHORT(PPP_PAP, nakoutp);
2090 PUTCHAR(CI_AUTHTYPE, nakoutp);
2094 PUTCHAR(CILEN_SHORT, nakoutp);
2095 PUTSHORT(PPP_EAP, nakoutp);
2100 PUTCHAR(CILEN_CHAP, nakoutp);
2101 PUTSHORT(PPP_CHAP, nakoutp);
2102 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2107 PUTCHAR(CILEN_SHORT, nakoutp);
2108 PUTSHORT(PPP_PAP, nakoutp);
2117 cilen != CILEN_LQR) {
2122 GETSHORT(cishort, p);
2129 if (cishort != PPP_LQR) {
2131 PUTCHAR(CI_QUALITY, nakoutp);
2132 PUTCHAR(CILEN_LQR, nakoutp);
2133 PUTSHORT(PPP_LQR, nakoutp);
2134 PUTLONG(ao->lqr_period, nakoutp);
2140 case CI_MAGICNUMBER:
2141 if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
2142 cilen != CILEN_LONG) {
2151 if (go->neg_magicnumber &&
2152 cilong == go->magicnumber) {
2155 PUTCHAR(CI_MAGICNUMBER, nakoutp);
2156 PUTCHAR(CILEN_LONG, nakoutp);
2157 PUTLONG(cilong, nakoutp);
2160 ho->neg_magicnumber = 1;
2161 ho->magicnumber = cilong;
2165 case CI_PCOMPRESSION:
2166 if (!ao->neg_pcompression ||
2167 cilen != CILEN_VOID) {
2171 ho->neg_pcompression = 1;
2174 case CI_ACCOMPRESSION:
2175 if (!ao->neg_accompression ||
2176 cilen != CILEN_VOID) {
2180 ho->neg_accompression = 1;
2183 #ifdef HAVE_MULTILINK 2187 || cilen != CILEN_SHORT) {
2192 GETSHORT(cishort, p);
2201 #ifdef HAVE_MULTILINK
2204 || cilen != CILEN_VOID) {
2212 if (!ao->neg_endpoint ||
2213 cilen < CILEN_CHAR ||
2214 cilen > CILEN_CHAR + MAX_ENDP_LEN) {
2219 cilen -= CILEN_CHAR;
2220 ho->neg_endpoint = 1;
2221 ho->endpoint.class_ = cichar;
2222 ho->endpoint.length = cilen;
2223 MEMCPY(ho->endpoint.value, p, cilen);
2228 LCPDEBUG((
"lcp_reqci: rcvd unknown option %d", citype));
2234 if (orc == CONFACK &&
2238 if (orc == CONFNAK) {
2239 if (reject_if_disagree
2240 && citype != CI_MAGICNUMBER) {
2248 if (orc == CONFREJ) {
2251 MEMCPY(rejp, cip, cilen);
2252 INCPTR(cilen, rejp);
2271 *lenp = nakoutp - (u_char*)nakp->
payload;
2272 MEMCPY(inp, nakp->
payload, *lenp);
2282 LCPDEBUG((
"lcp_reqci: returning CONF%s.", CODENAME(rc)));
2290 static void lcp_up(fsm *f) {
2291 ppp_pcb *pcb = f->pcb;
2292 lcp_options *wo = &pcb->lcp_wantoptions;
2293 lcp_options *ho = &pcb->lcp_hisoptions;
2294 lcp_options *go = &pcb->lcp_gotoptions;
2295 lcp_options *ao = &pcb->lcp_allowoptions;
2298 if (!go->neg_magicnumber)
2299 go->magicnumber = 0;
2300 if (!ho->neg_magicnumber)
2301 ho->magicnumber = 0;
2312 mtu = ho->neg_mru? ho->mru: PPP_MRU;
2313 mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU;
2314 #ifdef HAVE_MULTILINK 2315 if (!(multilink && go->neg_mrru && ho->neg_mrru))
2317 netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru));
2318 ppp_send_config(pcb, mtu,
2319 (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
2320 ho->neg_pcompression, ho->neg_accompression);
2321 ppp_recv_config(pcb, mru,
2322 (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
2323 go->neg_pcompression, go->neg_accompression);
2326 pcb->peer_mru = ho->mru;
2328 lcp_echo_lowerup(f->pcb);
2330 link_established(pcb);
2339 static void lcp_down(fsm *f) {
2340 ppp_pcb *pcb = f->pcb;
2341 lcp_options *go = &pcb->lcp_gotoptions;
2343 lcp_echo_lowerdown(f->pcb);
2347 ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0);
2348 ppp_recv_config(pcb, PPP_MRU,
2349 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
2350 go->neg_pcompression, go->neg_accompression);
2351 pcb->peer_mru = PPP_MRU;
2358 static void lcp_starting(fsm *f) {
2359 ppp_pcb *pcb = f->pcb;
2367 static void lcp_finished(fsm *f) {
2368 ppp_pcb *pcb = f->pcb;
2369 link_terminated(pcb);
2373 #if PRINTPKT_SUPPORT 2377 static const char*
const lcp_codenames[] = {
2378 "ConfReq",
"ConfAck",
"ConfNak",
"ConfRej",
2379 "TermReq",
"TermAck",
"CodeRej",
"ProtRej",
2380 "EchoReq",
"EchoRep",
"DiscReq",
"Ident",
2384 static int lcp_printpkt(
const u_char *p,
int plen,
2385 void (*printer) (
void *,
const char *, ...),
void *arg) {
2386 int code, id,
len, olen, i;
2387 const u_char *pstart, *optend;
2391 if (plen < HEADERLEN)
2397 if (len < HEADERLEN || len > plen)
2400 if (code >= 1 && code <= (
int)LWIP_ARRAYSIZE(lcp_codenames))
2401 printer(arg,
" %s", lcp_codenames[code-1]);
2403 printer(arg,
" code=0x%x", code);
2404 printer(arg,
" id=0x%x",
id);
2416 if (olen < 2 || olen > len) {
2424 if (olen == CILEN_SHORT) {
2426 GETSHORT(cishort, p);
2427 printer(arg,
"mru %d", cishort);
2431 if (olen == CILEN_LONG) {
2434 printer(arg,
"asyncmap 0x%x", cilong);
2438 if (olen >= CILEN_SHORT) {
2440 printer(arg,
"auth ");
2441 GETSHORT(cishort, p);
2445 printer(arg,
"pap");
2450 printer(arg,
"chap");
2454 printer(arg,
" MD5");
2458 case CHAP_MICROSOFT:
2459 printer(arg,
" MS");
2463 case CHAP_MICROSOFT_V2:
2464 printer(arg,
" MS-v2");
2476 printer(arg,
"eap");
2480 printer(arg,
"0x%x", cishort);
2486 if (olen >= CILEN_SHORT) {
2488 printer(arg,
"quality ");
2489 GETSHORT(cishort, p);
2492 printer(arg,
"lqr");
2495 printer(arg,
"0x%x", cishort);
2501 if (olen >= CILEN_CHAR) {
2503 printer(arg,
"callback ");
2504 GETCHAR(cishort, p);
2507 printer(arg,
"CBCP");
2510 printer(arg,
"0x%x", cishort);
2514 case CI_MAGICNUMBER:
2515 if (olen == CILEN_LONG) {
2518 printer(arg,
"magic 0x%x", cilong);
2521 case CI_PCOMPRESSION:
2522 if (olen == CILEN_VOID) {
2524 printer(arg,
"pcomp");
2527 case CI_ACCOMPRESSION:
2528 if (olen == CILEN_VOID) {
2530 printer(arg,
"accomp");
2534 if (olen == CILEN_SHORT) {
2536 GETSHORT(cishort, p);
2537 printer(arg,
"mrru %d", cishort);
2541 if (olen == CILEN_VOID) {
2543 printer(arg,
"ssnhf");
2547 #ifdef HAVE_MULTILINK 2548 if (olen >= CILEN_CHAR) {
2551 GETCHAR(epd.class, p);
2552 epd.length = olen - CILEN_CHAR;
2553 if (epd.length > MAX_ENDP_LEN)
2554 epd.length = MAX_ENDP_LEN;
2555 if (epd.length > 0) {
2556 MEMCPY(epd.value, p, epd.length);
2559 printer(arg,
"endpoint [%s]", epdisc_to_str(&epd));
2562 printer(arg,
"endpoint");
2568 while (p < optend) {
2570 printer(arg,
" %.2x", code);
2578 if (len > 0 && *p >=
' ' && *p < 0x7f) {
2580 ppp_print_string(p, len, printer, arg);
2591 printer(arg,
" magic=0x%x", cilong);
2600 printer(arg,
" magic=0x%x", cilong);
2603 if (code == TIMEREM) {
2607 printer(arg,
" seconds=%u", cilong);
2612 ppp_print_string(p, len, printer, arg);
2622 for (i = 0; i < len && i < 32; ++i) {
2624 printer(arg,
" %.2x", code);
2627 printer(arg,
" ...");
2639 static void LcpLinkFailure(fsm *f) {
2640 ppp_pcb *pcb = f->pcb;
2641 if (f->state == PPP_FSM_OPENED) {
2642 ppp_info(
"No response to %d echo-requests", pcb->lcp_echos_pending);
2643 ppp_notice(
"Serial link appears to be disconnected.");
2644 pcb->err_code = PPPERR_PEERDEAD;
2645 lcp_close(pcb,
"Peer not responding");
2653 static void LcpEchoCheck(fsm *f) {
2654 ppp_pcb *pcb = f->pcb;
2656 LcpSendEchoRequest (f);
2657 if (f->state != PPP_FSM_OPENED)
2663 if (pcb->lcp_echo_timer_running)
2664 ppp_warn(
"assertion lcp_echo_timer_running==0 failed");
2665 TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval);
2666 pcb->lcp_echo_timer_running = 1;
2673 static void LcpEchoTimeout(
void *arg) {
2675 ppp_pcb *pcb = f->pcb;
2676 if (pcb->lcp_echo_timer_running != 0) {
2677 pcb->lcp_echo_timer_running = 0;
2678 LcpEchoCheck ((fsm *) arg);
2686 static void lcp_received_echo_reply(fsm *f,
int id, u_char *inp,
int len) {
2687 ppp_pcb *pcb = f->pcb;
2688 lcp_options *go = &pcb->lcp_gotoptions;
2694 ppp_dbglog(
"lcp: received short Echo-Reply, length %d", len);
2697 GETLONG(magic_val, inp);
2698 if (go->neg_magicnumber
2699 && magic_val == go->magicnumber) {
2700 ppp_warn(
"appear to have received our own echo-reply!");
2705 pcb->lcp_echos_pending = 0;
2712 static void LcpSendEchoRequest(fsm *f) {
2713 ppp_pcb *pcb = f->pcb;
2714 lcp_options *go = &pcb->lcp_gotoptions;
2716 u_char pkt[4], *pktp;
2721 if (pcb->settings.lcp_echo_fails != 0) {
2722 if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) {
2724 pcb->lcp_echos_pending = 0;
2728 #if PPP_LCP_ADAPTIVE 2733 if (pcb->settings.lcp_echo_adaptive) {
2734 static unsigned int last_pkts_in = 0;
2736 #if PPP_STATS_SUPPORT 2737 update_link_stats(f->unit);
2738 link_stats_valid = 0;
2741 if (link_stats.pkts_in != last_pkts_in) {
2742 last_pkts_in = link_stats.pkts_in;
2751 if (f->state == PPP_FSM_OPENED) {
2752 lcp_magic = go->magicnumber;
2754 PUTLONG(lcp_magic, pktp);
2755 fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt);
2756 ++pcb->lcp_echos_pending;
2764 static void lcp_echo_lowerup(ppp_pcb *pcb) {
2765 fsm *f = &pcb->lcp_fsm;
2768 pcb->lcp_echos_pending = 0;
2769 pcb->lcp_echo_number = 0;
2770 pcb->lcp_echo_timer_running = 0;
2773 if (pcb->settings.lcp_echo_interval != 0)
2781 static void lcp_echo_lowerdown(ppp_pcb *pcb) {
2782 fsm *f = &pcb->lcp_fsm;
2784 if (pcb->lcp_echo_timer_running != 0) {
2785 UNTIMEOUT (LcpEchoTimeout, f);
2786 pcb->lcp_echo_timer_running = 0;
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
#define LWIP_UNUSED_ARG(x)
u8_t pbuf_free(struct pbuf *p)