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 && pcb->phase != PPP_PHASE_MASTER)
427 new_phase(pcb, PPP_PHASE_TERMINATE);
429 if (f->flags & DELAYED_UP) {
430 UNTIMEOUT(lcp_delayed_up, f);
431 f->state = PPP_FSM_STOPPED;
435 fsm_close(f, reason);
436 if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) {
444 f->flags &= ~DELAYED_UP;
453 void lcp_lowerup(ppp_pcb *pcb) {
454 lcp_options *wo = &pcb->lcp_wantoptions;
455 fsm *f = &pcb->lcp_fsm;
461 if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0
462 || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff),
463 wo->neg_pcompression, wo->neg_accompression) < 0)
465 pcb->peer_mru = PPP_MRU;
467 if (pcb->settings.listen_time != 0) {
468 f->flags |= DELAYED_UP;
469 TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time);
478 void lcp_lowerdown(ppp_pcb *pcb) {
479 fsm *f = &pcb->lcp_fsm;
481 if (f->flags & DELAYED_UP) {
482 f->flags &= ~DELAYED_UP;
483 UNTIMEOUT(lcp_delayed_up, f);
492 static void lcp_delayed_up(
void *arg) {
495 if (f->flags & DELAYED_UP) {
496 f->flags &= ~DELAYED_UP;
505 static void lcp_input(ppp_pcb *pcb, u_char *p,
int len) {
506 fsm *f = &pcb->lcp_fsm;
508 if (f->flags & DELAYED_UP) {
509 f->flags &= ~DELAYED_UP;
510 UNTIMEOUT(lcp_delayed_up, f);
513 fsm_input(f, p, len);
519 static int lcp_extcode(fsm *f,
int code,
int id, u_char *inp,
int len) {
520 ppp_pcb *pcb = f->pcb;
521 lcp_options *go = &pcb->lcp_gotoptions;
526 lcp_rprotrej(f, inp, len);
530 if (f->state != PPP_FSM_OPENED)
533 PUTLONG(go->magicnumber, magp);
534 fsm_sdata(f, ECHOREP,
id, inp, len);
538 lcp_received_echo_reply(f,
id, inp, len);
558 static void lcp_rprotrej(fsm *f, u_char *inp,
int len) {
560 const struct protent *protp;
567 LCPDEBUG((
"lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
577 if( f->state != PPP_FSM_OPENED ){
578 LCPDEBUG((
"Protocol-Reject discarded: LCP in state %d", f->state));
583 pname = protocol_name(prot);
589 for (i = 0; (protp = protocols[i]) != NULL; ++i)
590 if (protp->protocol == prot) {
593 ppp_dbglog(
"Protocol-Reject for '%s' (0x%x) received", pname,
597 ppp_dbglog(
"Protocol-Reject for 0x%x received", prot);
598 (*protp->protrej)(f->pcb);
604 ppp_warn(
"Protocol-Reject for unsupported protocol '%s' (0x%x)", pname,
608 ppp_warn(
"Protocol-Reject for unsupported protocol 0x%x", prot);
616 static void lcp_protrej(ppp_pcb *pcb) {
620 ppp_error(
"Received Protocol-Reject for LCP!");
621 fsm_protreject(&pcb->lcp_fsm);
628 void lcp_sprotrej(ppp_pcb *pcb, u_char *p,
int len) {
629 fsm *f = &pcb->lcp_fsm;
639 fsm_sdata(f, PROTREJ, ++f->id,
647 static void lcp_resetci(fsm *f) {
648 ppp_pcb *pcb = f->pcb;
649 lcp_options *wo = &pcb->lcp_wantoptions;
650 lcp_options *go = &pcb->lcp_gotoptions;
651 lcp_options *ao = &pcb->lcp_allowoptions;
656 if (pcb->settings.user && pcb->settings.passwd) {
658 if (pcb->settings.refuse_pap) {
663 if (pcb->settings.refuse_chap) {
664 ao->chap_mdtype &= ~MDTYPE_MD5;
667 if (pcb->settings.refuse_mschap) {
668 ao->chap_mdtype &= ~MDTYPE_MICROSOFT;
670 if (pcb->settings.refuse_mschap_v2) {
671 ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2;
674 ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE);
677 if (pcb->settings.refuse_eap) {
684 if (pcb->settings.auth_required) {
686 if (!pcb->settings.refuse_pap) {
691 if (!pcb->settings.refuse_chap) {
692 wo->chap_mdtype |= MDTYPE_MD5;
695 if (!pcb->settings.refuse_mschap) {
696 wo->chap_mdtype |= MDTYPE_MICROSOFT;
698 if (!pcb->settings.refuse_mschap_v2) {
699 wo->chap_mdtype |= MDTYPE_MICROSOFT_V2;
702 wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE);
705 if (!pcb->settings.refuse_eap) {
718 ao->chap_mdtype = MDTYPE_NONE;
725 PPPDEBUG(LOG_DEBUG, (
"ppp: auth protocols:"));
727 PPPDEBUG(LOG_DEBUG, (
" PAP=%d", ao->neg_upap));
730 PPPDEBUG(LOG_DEBUG, (
" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5)));
732 PPPDEBUG(LOG_DEBUG, (
" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2)));
736 PPPDEBUG(LOG_DEBUG, (
" EAP=%d", ao->neg_eap));
738 PPPDEBUG(LOG_DEBUG, (
"\n"));
742 wo->magicnumber = magic();
745 #ifdef HAVE_MULTILINK 750 go->neg_endpoint = 0;
751 #ifdef HAVE_MULTILINK 754 if (pcb->settings.noendpoint)
755 ao->neg_endpoint = 0;
756 pcb->peer_mru = PPP_MRU;
766 static int lcp_cilen(fsm *f) {
767 ppp_pcb *pcb = f->pcb;
768 lcp_options *go = &pcb->lcp_gotoptions;
770 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) 772 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) 774 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) 775 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) 777 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) 779 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) 785 return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) +
786 LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
788 LENCISHORT(go->neg_eap) +
792 LENCICHAP(!go->neg_eap && go->neg_chap) +
795 LENCICHAP(go->neg_chap) +
799 #
if EAP_SUPPORT && CHAP_SUPPORT
800 LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) +
802 #
if EAP_SUPPORT && !CHAP_SUPPORT
803 LENCISHORT(!go->neg_eap && go->neg_upap) +
805 #
if !EAP_SUPPORT && CHAP_SUPPORT
806 LENCISHORT(!go->neg_chap && go->neg_upap) +
808 #
if !EAP_SUPPORT && !CHAP_SUPPORT
809 LENCISHORT(go->neg_upap) +
813 LENCILQR(go->neg_lqr) +
815 LENCICBCP(go->neg_cbcp) +
816 LENCILONG(go->neg_magicnumber) +
817 LENCIVOID(go->neg_pcompression) +
818 LENCIVOID(go->neg_accompression) +
819 #ifdef HAVE_MULTILINK
820 LENCISHORT(go->neg_mrru) +
822 LENCIVOID(go->neg_ssnhf) +
823 (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
830 static void lcp_addci(fsm *f, u_char *ucp,
int *lenp) {
831 ppp_pcb *pcb = f->pcb;
832 lcp_options *go = &pcb->lcp_gotoptions;
833 u_char *start_ucp = ucp;
835 #define ADDCIVOID(opt, neg) \ 838 PUTCHAR(CILEN_VOID, ucp); \ 840 #define ADDCISHORT(opt, neg, val) \ 843 PUTCHAR(CILEN_SHORT, ucp); \ 844 PUTSHORT(val, ucp); \ 847 #define ADDCICHAP(opt, neg, val) \ 849 PUTCHAR((opt), ucp); \ 850 PUTCHAR(CILEN_CHAP, ucp); \ 851 PUTSHORT(PPP_CHAP, ucp); \ 852 PUTCHAR((CHAP_DIGEST(val)), ucp); \ 855 #define ADDCILONG(opt, neg, val) \ 858 PUTCHAR(CILEN_LONG, ucp); \ 862 #define ADDCILQR(opt, neg, val) \ 865 PUTCHAR(CILEN_LQR, ucp); \ 866 PUTSHORT(PPP_LQR, ucp); \ 870 #define ADDCICHAR(opt, neg, val) \ 873 PUTCHAR(CILEN_CHAR, ucp); \ 876 #define ADDCIENDP(opt, neg, class, val, len) \ 880 PUTCHAR(CILEN_CHAR + len, ucp); \ 881 PUTCHAR(class, ucp); \ 882 for (i = 0; i < len; ++i) \ 883 PUTCHAR(val[i], ucp); \ 886 ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
887 ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
890 ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
894 ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
897 ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
901 #if EAP_SUPPORT && CHAP_SUPPORT 902 ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP);
904 #if EAP_SUPPORT && !CHAP_SUPPORT 905 ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP);
907 #if !EAP_SUPPORT && CHAP_SUPPORT 908 ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
910 #if !EAP_SUPPORT && !CHAP_SUPPORT 911 ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP);
915 ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
917 ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
918 ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
919 ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
920 ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
921 #ifdef HAVE_MULTILINK 922 ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
924 ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
925 ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_,
926 go->endpoint.value, go->endpoint.length);
928 if (ucp - start_ucp != *lenp) {
930 ppp_error(
"Bug in lcp_addci: wrong length");
943 static int lcp_ackci(fsm *f, u_char *p,
int len) {
944 ppp_pcb *pcb = f->pcb;
945 lcp_options *go = &pcb->lcp_gotoptions;
946 u_char cilen, citype, cichar;
955 #define ACKCIVOID(opt, neg) \ 957 if ((len -= CILEN_VOID) < 0) \ 959 GETCHAR(citype, p); \ 961 if (cilen != CILEN_VOID || \ 965 #define ACKCISHORT(opt, neg, val) \ 967 if ((len -= CILEN_SHORT) < 0) \ 969 GETCHAR(citype, p); \ 971 if (cilen != CILEN_SHORT || \ 974 GETSHORT(cishort, p); \ 975 if (cishort != val) \ 978 #define ACKCICHAR(opt, neg, val) \ 980 if ((len -= CILEN_CHAR) < 0) \ 982 GETCHAR(citype, p); \ 984 if (cilen != CILEN_CHAR || \ 987 GETCHAR(cichar, p); \ 992 #define ACKCICHAP(opt, neg, val) \ 994 if ((len -= CILEN_CHAP) < 0) \ 996 GETCHAR(citype, p); \ 998 if (cilen != CILEN_CHAP || \ 1001 GETSHORT(cishort, p); \ 1002 if (cishort != PPP_CHAP) \ 1004 GETCHAR(cichar, p); \ 1005 if (cichar != (CHAP_DIGEST(val))) \ 1009 #define ACKCILONG(opt, neg, val) \ 1011 if ((len -= CILEN_LONG) < 0) \ 1013 GETCHAR(citype, p); \ 1014 GETCHAR(cilen, p); \ 1015 if (cilen != CILEN_LONG || \ 1018 GETLONG(cilong, p); \ 1019 if (cilong != val) \ 1023 #define ACKCILQR(opt, neg, val) \ 1025 if ((len -= CILEN_LQR) < 0) \ 1027 GETCHAR(citype, p); \ 1028 GETCHAR(cilen, p); \ 1029 if (cilen != CILEN_LQR || \ 1032 GETSHORT(cishort, p); \ 1033 if (cishort != PPP_LQR) \ 1035 GETLONG(cilong, p); \ 1036 if (cilong != val) \ 1040 #define ACKCIENDP(opt, neg, class, val, vlen) \ 1043 if ((len -= CILEN_CHAR + vlen) < 0) \ 1045 GETCHAR(citype, p); \ 1046 GETCHAR(cilen, p); \ 1047 if (cilen != CILEN_CHAR + vlen || \ 1050 GETCHAR(cichar, p); \ 1051 if (cichar != class) \ 1053 for (i = 0; i < vlen; ++i) { \ 1054 GETCHAR(cichar, p); \ 1055 if (cichar != val[i]) \ 1060 ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
1061 ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
1064 ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
1068 ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
1071 ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
1075 #if EAP_SUPPORT && CHAP_SUPPORT 1076 ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP);
1078 #if EAP_SUPPORT && !CHAP_SUPPORT 1079 ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP);
1081 #if !EAP_SUPPORT && CHAP_SUPPORT 1082 ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
1084 #if !EAP_SUPPORT && !CHAP_SUPPORT 1085 ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP);
1089 ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1091 ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
1092 ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
1093 ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
1094 ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
1095 #ifdef HAVE_MULTILINK 1096 ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
1098 ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
1099 ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_,
1100 go->endpoint.value, go->endpoint.length);
1109 LCPDEBUG((
"lcp_acki: received bad Ack!"));
1123 static int lcp_nakci(fsm *f, u_char *p,
int len,
int treat_as_reject) {
1124 ppp_pcb *pcb = f->pcb;
1125 lcp_options *go = &pcb->lcp_gotoptions;
1126 lcp_options *wo = &pcb->lcp_wantoptions;
1127 u_char citype, cichar, *next;
1132 int looped_back = 0;
1135 BZERO(&no,
sizeof(no));
1143 #define NAKCIVOID(opt, neg) \ 1145 len >= CILEN_VOID && \ 1146 p[1] == CILEN_VOID && \ 1148 len -= CILEN_VOID; \ 1149 INCPTR(CILEN_VOID, p); \ 1154 #define NAKCICHAP(opt, neg, code) \ 1156 len >= CILEN_CHAP && \ 1157 p[1] == CILEN_CHAP && \ 1159 len -= CILEN_CHAP; \ 1161 GETSHORT(cishort, p); \ 1162 GETCHAR(cichar, p); \ 1167 #define NAKCICHAR(opt, neg, code) \ 1169 len >= CILEN_CHAR && \ 1170 p[1] == CILEN_CHAR && \ 1172 len -= CILEN_CHAR; \ 1174 GETCHAR(cichar, p); \ 1178 #define NAKCISHORT(opt, neg, code) \ 1180 len >= CILEN_SHORT && \ 1181 p[1] == CILEN_SHORT && \ 1183 len -= CILEN_SHORT; \ 1185 GETSHORT(cishort, p); \ 1189 #define NAKCILONG(opt, neg, code) \ 1191 len >= CILEN_LONG && \ 1192 p[1] == CILEN_LONG && \ 1194 len -= CILEN_LONG; \ 1196 GETLONG(cilong, p); \ 1201 #define NAKCILQR(opt, neg, code) \ 1203 len >= CILEN_LQR && \ 1204 p[1] == CILEN_LQR && \ 1208 GETSHORT(cishort, p); \ 1209 GETLONG(cilong, p); \ 1214 #define NAKCIENDP(opt, neg) \ 1216 len >= CILEN_CHAR && \ 1218 p[1] >= CILEN_CHAR && \ 1237 if (go->neg_mru && go->mru != PPP_DEFMRU) {
1238 NAKCISHORT(CI_MRU, neg_mru,
1239 if (cishort <= wo->mru || cishort <= PPP_DEFMRU)
1247 if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
1248 NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
1249 try_.asyncmap = go->asyncmap | cilong;
1269 && len >= CILEN_SHORT
1270 && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
1274 no.neg_chap = go->neg_chap;
1277 no.neg_upap = go->neg_upap;
1280 no.neg_eap = go->neg_eap;
1283 GETSHORT(cishort, p);
1286 if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
1310 if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
1317 if (CHAP_CANDIGEST(go->chap_mdtype, cichar))
1318 try_.chap_mdtype = CHAP_MDTYPE_D(cichar);
1326 if (cichar != CHAP_DIGEST(go->chap_mdtype)) {
1327 if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) {
1329 try_.chap_mdtype = CHAP_MDTYPE_D(cichar);
1332 try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype));
1333 if (try_.chap_mdtype == MDTYPE_NONE)
1361 if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap)
1362 ppp_dbglog(
"Unexpected Conf-Nak for EAP");
1386 p += cilen - CILEN_SHORT;
1396 NAKCILQR(CI_QUALITY, neg_lqr,
1397 if (cishort != PPP_LQR)
1400 try_.lqr_period = cilong;
1407 NAKCICHAR(CI_CALLBACK, neg_cbcp,
1415 NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1416 try_.magicnumber = magic();
1425 NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1426 NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1428 #ifdef HAVE_MULTILINK 1434 NAKCISHORT(CI_MRRU, neg_mrru,
1435 if (treat_as_reject)
1437 else if (cishort <= wo->mrru)
1438 try_.mrru = cishort;
1449 NAKCIVOID(CI_SSNHF, neg_ssnhf);
1455 NAKCIENDP(CI_EPDISC, neg_endpoint);
1473 while (len >= CILEN_VOID) {
1476 if (cilen < CILEN_VOID || (len -= cilen) < 0)
1478 next = p + cilen - 2;
1482 if ((go->neg_mru && go->mru != PPP_DEFMRU)
1483 || no.neg_mru || cilen != CILEN_SHORT)
1485 GETSHORT(cishort, p);
1486 if (cishort < PPP_DEFMRU) {
1492 if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1493 || no.neg_asyncmap || cilen != CILEN_LONG)
1499 || go->neg_chap || no.neg_chap
1502 || go->neg_upap || no.neg_upap
1505 || go->neg_eap || no.neg_eap
1510 case CI_MAGICNUMBER:
1511 if (go->neg_magicnumber || no.neg_magicnumber ||
1512 cilen != CILEN_LONG)
1515 case CI_PCOMPRESSION:
1516 if (go->neg_pcompression || no.neg_pcompression
1517 || cilen != CILEN_VOID)
1520 case CI_ACCOMPRESSION:
1521 if (go->neg_accompression || no.neg_accompression
1522 || cilen != CILEN_VOID)
1527 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1531 #ifdef HAVE_MULTILINK 1533 if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1538 if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1543 if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1556 if (f->state != PPP_FSM_OPENED) {
1558 if (++try_.numloops >= pcb->settings.lcp_loopbackfail) {
1559 ppp_notice(
"Serial line is looped back.");
1560 pcb->err_code = PPPERR_LOOPBACK;
1561 lcp_close(f->pcb,
"Loopback detected");
1571 LCPDEBUG((
"lcp_nakci: received bad Nak!"));
1585 static int lcp_rejci(fsm *f, u_char *p,
int len) {
1586 ppp_pcb *pcb = f->pcb;
1587 lcp_options *go = &pcb->lcp_gotoptions;
1600 #define REJCIVOID(opt, neg) \ 1602 len >= CILEN_VOID && \ 1603 p[1] == CILEN_VOID && \ 1605 len -= CILEN_VOID; \ 1606 INCPTR(CILEN_VOID, p); \ 1609 #define REJCISHORT(opt, neg, val) \ 1611 len >= CILEN_SHORT && \ 1612 p[1] == CILEN_SHORT && \ 1614 len -= CILEN_SHORT; \ 1616 GETSHORT(cishort, p); \ 1618 if (cishort != val) \ 1623 #if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT 1624 #define REJCICHAP(opt, neg, val) \ 1626 len >= CILEN_CHAP && \ 1627 p[1] == CILEN_CHAP && \ 1629 len -= CILEN_CHAP; \ 1631 GETSHORT(cishort, p); \ 1632 GETCHAR(cichar, p); \ 1634 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1637 try_.neg_eap = try_.neg_upap = 0; \ 1641 #if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT 1642 #define REJCICHAP(opt, neg, val) \ 1644 len >= CILEN_CHAP && \ 1645 p[1] == CILEN_CHAP && \ 1647 len -= CILEN_CHAP; \ 1649 GETSHORT(cishort, p); \ 1650 GETCHAR(cichar, p); \ 1652 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1655 try_.neg_upap = 0; \ 1659 #if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT 1660 #define REJCICHAP(opt, neg, val) \ 1662 len >= CILEN_CHAP && \ 1663 p[1] == CILEN_CHAP && \ 1665 len -= CILEN_CHAP; \ 1667 GETSHORT(cishort, p); \ 1668 GETCHAR(cichar, p); \ 1670 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1677 #if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT 1678 #define REJCICHAP(opt, neg, val) \ 1680 len >= CILEN_CHAP && \ 1681 p[1] == CILEN_CHAP && \ 1683 len -= CILEN_CHAP; \ 1685 GETSHORT(cishort, p); \ 1686 GETCHAR(cichar, p); \ 1688 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ 1694 #define REJCILONG(opt, neg, val) \ 1696 len >= CILEN_LONG && \ 1697 p[1] == CILEN_LONG && \ 1699 len -= CILEN_LONG; \ 1701 GETLONG(cilong, p); \ 1703 if (cilong != val) \ 1708 #define REJCILQR(opt, neg, val) \ 1710 len >= CILEN_LQR && \ 1711 p[1] == CILEN_LQR && \ 1715 GETSHORT(cishort, p); \ 1716 GETLONG(cilong, p); \ 1718 if (cishort != PPP_LQR || cilong != val) \ 1723 #define REJCICBCP(opt, neg, val) \ 1725 len >= CILEN_CBCP && \ 1726 p[1] == CILEN_CBCP && \ 1728 len -= CILEN_CBCP; \ 1730 GETCHAR(cichar, p); \ 1732 if (cichar != val) \ 1736 #define REJCIENDP(opt, neg, class, val, vlen) \ 1738 len >= CILEN_CHAR + vlen && \ 1740 p[1] == CILEN_CHAR + vlen) { \ 1742 len -= CILEN_CHAR + vlen; \ 1744 GETCHAR(cichar, p); \ 1745 if (cichar != class) \ 1747 for (i = 0; i < vlen; ++i) { \ 1748 GETCHAR(cichar, p); \ 1749 if (cichar != val[i]) \ 1755 REJCISHORT(CI_MRU, neg_mru, go->mru);
1756 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1758 REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
1762 REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
1763 if (!go->neg_chap) {
1766 REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1775 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1777 REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1778 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1779 REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1780 REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1781 #ifdef HAVE_MULTILINK 1782 REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1784 REJCIVOID(CI_SSNHF, neg_ssnhf);
1785 REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_,
1786 go->endpoint.value, go->endpoint.length);
1796 if (f->state != PPP_FSM_OPENED)
1801 LCPDEBUG((
"lcp_rejci: received bad Reject!"));
1816 static int lcp_reqci(fsm *f, u_char *inp,
int *lenp,
int reject_if_disagree) {
1817 ppp_pcb *pcb = f->pcb;
1818 lcp_options *go = &pcb->lcp_gotoptions;
1819 lcp_options *ho = &pcb->lcp_hisoptions;
1820 lcp_options *ao = &pcb->lcp_allowoptions;
1822 int cilen, citype, cichar;
1836 BZERO(ho,
sizeof(*ho));
1850 nakoutp = (u_char*)nakp->
payload;
1858 LCPDEBUG((
"lcp_reqci: bad CI length!"));
1873 cilen != CILEN_SHORT) {
1877 GETSHORT(cishort, p);
1884 if (cishort < PPP_MINMRU) {
1886 PUTCHAR(CI_MRU, nakoutp);
1887 PUTCHAR(CILEN_SHORT, nakoutp);
1888 PUTSHORT(PPP_MINMRU, nakoutp);
1896 if (!ao->neg_asyncmap ||
1897 cilen != CILEN_LONG) {
1907 if ((ao->asyncmap & ~cilong) != 0) {
1909 PUTCHAR(CI_ASYNCMAP, nakoutp);
1910 PUTCHAR(CILEN_LONG, nakoutp);
1911 PUTLONG(ao->asyncmap | cilong, nakoutp);
1914 ho->neg_asyncmap = 1;
1915 ho->asyncmap = cilong;
1919 if (cilen < CILEN_SHORT ||
1934 ppp_dbglog(
"No auth is possible");
1938 GETSHORT(cishort, p);
1952 if (cishort == PPP_PAP) {
1961 || cilen != CILEN_SHORT) {
1962 LCPDEBUG((
"lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1966 if (!ao->neg_upap) {
1968 PUTCHAR(CI_AUTHTYPE, nakoutp);
1971 PUTCHAR(CILEN_SHORT, nakoutp);
1972 PUTSHORT(PPP_EAP, nakoutp);
1976 PUTCHAR(CILEN_CHAP, nakoutp);
1977 PUTSHORT(PPP_CHAP, nakoutp);
1978 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
1990 if (cishort == PPP_CHAP) {
1999 cilen != CILEN_CHAP) {
2000 LCPDEBUG((
"lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
2004 if (!ao->neg_chap) {
2006 PUTCHAR(CI_AUTHTYPE, nakoutp);
2007 PUTCHAR(CILEN_SHORT, nakoutp);
2010 PUTSHORT(PPP_EAP, nakoutp);
2015 PUTSHORT(PPP_PAP, nakoutp);
2023 if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) {
2029 PUTCHAR(CI_AUTHTYPE, nakoutp);
2030 PUTCHAR(CILEN_CHAP, nakoutp);
2031 PUTSHORT(PPP_CHAP, nakoutp);
2032 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2035 ho->chap_mdtype = CHAP_MDTYPE_D(cichar);
2041 if (cishort == PPP_EAP) {
2050 cilen != CILEN_SHORT) {
2051 LCPDEBUG((
"lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
2057 PUTCHAR(CI_AUTHTYPE, nakoutp);
2060 PUTCHAR(CILEN_CHAP, nakoutp);
2061 PUTSHORT(PPP_CHAP, nakoutp);
2062 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2067 PUTCHAR(CILEN_SHORT, nakoutp);
2068 PUTSHORT(PPP_PAP, nakoutp);
2086 PUTCHAR(CI_AUTHTYPE, nakoutp);
2090 PUTCHAR(CILEN_SHORT, nakoutp);
2091 PUTSHORT(PPP_EAP, nakoutp);
2096 PUTCHAR(CILEN_CHAP, nakoutp);
2097 PUTSHORT(PPP_CHAP, nakoutp);
2098 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2103 PUTCHAR(CILEN_SHORT, nakoutp);
2104 PUTSHORT(PPP_PAP, nakoutp);
2113 cilen != CILEN_LQR) {
2118 GETSHORT(cishort, p);
2125 if (cishort != PPP_LQR) {
2127 PUTCHAR(CI_QUALITY, nakoutp);
2128 PUTCHAR(CILEN_LQR, nakoutp);
2129 PUTSHORT(PPP_LQR, nakoutp);
2130 PUTLONG(ao->lqr_period, nakoutp);
2136 case CI_MAGICNUMBER:
2137 if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
2138 cilen != CILEN_LONG) {
2147 if (go->neg_magicnumber &&
2148 cilong == go->magicnumber) {
2151 PUTCHAR(CI_MAGICNUMBER, nakoutp);
2152 PUTCHAR(CILEN_LONG, nakoutp);
2153 PUTLONG(cilong, nakoutp);
2156 ho->neg_magicnumber = 1;
2157 ho->magicnumber = cilong;
2161 case CI_PCOMPRESSION:
2162 if (!ao->neg_pcompression ||
2163 cilen != CILEN_VOID) {
2167 ho->neg_pcompression = 1;
2170 case CI_ACCOMPRESSION:
2171 if (!ao->neg_accompression ||
2172 cilen != CILEN_VOID) {
2176 ho->neg_accompression = 1;
2179 #ifdef HAVE_MULTILINK 2183 || cilen != CILEN_SHORT) {
2188 GETSHORT(cishort, p);
2197 #ifdef HAVE_MULTILINK
2200 || cilen != CILEN_VOID) {
2208 if (!ao->neg_endpoint ||
2209 cilen < CILEN_CHAR ||
2210 cilen > CILEN_CHAR + MAX_ENDP_LEN) {
2215 cilen -= CILEN_CHAR;
2216 ho->neg_endpoint = 1;
2217 ho->endpoint.class_ = cichar;
2218 ho->endpoint.length = cilen;
2219 MEMCPY(ho->endpoint.value, p, cilen);
2224 LCPDEBUG((
"lcp_reqci: rcvd unknown option %d", citype));
2230 if (orc == CONFACK &&
2234 if (orc == CONFNAK) {
2235 if (reject_if_disagree
2236 && citype != CI_MAGICNUMBER) {
2244 if (orc == CONFREJ) {
2247 MEMCPY(rejp, cip, cilen);
2248 INCPTR(cilen, rejp);
2267 *lenp = nakoutp - (u_char*)nakp->
payload;
2278 LCPDEBUG((
"lcp_reqci: returning CONF%s.", CODENAME(rc)));
2286 static void lcp_up(fsm *f) {
2287 ppp_pcb *pcb = f->pcb;
2288 lcp_options *wo = &pcb->lcp_wantoptions;
2289 lcp_options *ho = &pcb->lcp_hisoptions;
2290 lcp_options *go = &pcb->lcp_gotoptions;
2291 lcp_options *ao = &pcb->lcp_allowoptions;
2294 if (!go->neg_magicnumber)
2295 go->magicnumber = 0;
2296 if (!ho->neg_magicnumber)
2297 ho->magicnumber = 0;
2308 mtu = ho->neg_mru? ho->mru: PPP_MRU;
2309 mru = go->neg_mru?
LWIP_MAX(wo->mru, go->mru): PPP_MRU;
2310 #ifdef HAVE_MULTILINK 2311 if (!(multilink && go->neg_mrru && ho->neg_mrru))
2314 ppp_send_config(pcb, mtu,
2315 (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
2316 ho->neg_pcompression, ho->neg_accompression);
2317 ppp_recv_config(pcb, mru,
2318 (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
2319 go->neg_pcompression, go->neg_accompression);
2322 pcb->peer_mru = ho->mru;
2324 lcp_echo_lowerup(f->pcb);
2326 link_established(pcb);
2335 static void lcp_down(fsm *f) {
2336 ppp_pcb *pcb = f->pcb;
2337 lcp_options *go = &pcb->lcp_gotoptions;
2339 lcp_echo_lowerdown(f->pcb);
2343 ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0);
2344 ppp_recv_config(pcb, PPP_MRU,
2345 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
2346 go->neg_pcompression, go->neg_accompression);
2347 pcb->peer_mru = PPP_MRU;
2354 static void lcp_starting(fsm *f) {
2355 ppp_pcb *pcb = f->pcb;
2363 static void lcp_finished(fsm *f) {
2364 ppp_pcb *pcb = f->pcb;
2365 link_terminated(pcb);
2369 #if PRINTPKT_SUPPORT 2373 static const char*
const lcp_codenames[] = {
2374 "ConfReq",
"ConfAck",
"ConfNak",
"ConfRej",
2375 "TermReq",
"TermAck",
"CodeRej",
"ProtRej",
2376 "EchoReq",
"EchoRep",
"DiscReq",
"Ident",
2380 static int lcp_printpkt(
const u_char *p,
int plen,
2381 void (*printer) (
void *,
const char *, ...),
void *arg) {
2382 int code, id,
len, olen, i;
2383 const u_char *pstart, *optend;
2387 if (plen < HEADERLEN)
2393 if (len < HEADERLEN || len > plen)
2396 if (code >= 1 && code <= (
int)
sizeof(lcp_codenames) / (
int)
sizeof(
char *))
2397 printer(arg,
" %s", lcp_codenames[code-1]);
2399 printer(arg,
" code=0x%x", code);
2400 printer(arg,
" id=0x%x",
id);
2412 if (olen < 2 || olen > len) {
2420 if (olen == CILEN_SHORT) {
2422 GETSHORT(cishort, p);
2423 printer(arg,
"mru %d", cishort);
2427 if (olen == CILEN_LONG) {
2430 printer(arg,
"asyncmap 0x%x", cilong);
2434 if (olen >= CILEN_SHORT) {
2436 printer(arg,
"auth ");
2437 GETSHORT(cishort, p);
2441 printer(arg,
"pap");
2446 printer(arg,
"chap");
2450 printer(arg,
" MD5");
2454 case CHAP_MICROSOFT:
2455 printer(arg,
" MS");
2459 case CHAP_MICROSOFT_V2:
2460 printer(arg,
" MS-v2");
2472 printer(arg,
"eap");
2476 printer(arg,
"0x%x", cishort);
2482 if (olen >= CILEN_SHORT) {
2484 printer(arg,
"quality ");
2485 GETSHORT(cishort, p);
2488 printer(arg,
"lqr");
2491 printer(arg,
"0x%x", cishort);
2497 if (olen >= CILEN_CHAR) {
2499 printer(arg,
"callback ");
2500 GETCHAR(cishort, p);
2503 printer(arg,
"CBCP");
2506 printer(arg,
"0x%x", cishort);
2510 case CI_MAGICNUMBER:
2511 if (olen == CILEN_LONG) {
2514 printer(arg,
"magic 0x%x", cilong);
2517 case CI_PCOMPRESSION:
2518 if (olen == CILEN_VOID) {
2520 printer(arg,
"pcomp");
2523 case CI_ACCOMPRESSION:
2524 if (olen == CILEN_VOID) {
2526 printer(arg,
"accomp");
2530 if (olen == CILEN_SHORT) {
2532 GETSHORT(cishort, p);
2533 printer(arg,
"mrru %d", cishort);
2537 if (olen == CILEN_VOID) {
2539 printer(arg,
"ssnhf");
2543 #ifdef HAVE_MULTILINK 2544 if (olen >= CILEN_CHAR) {
2547 GETCHAR(epd.class, p);
2548 epd.length = olen - CILEN_CHAR;
2549 if (epd.length > MAX_ENDP_LEN)
2550 epd.length = MAX_ENDP_LEN;
2551 if (epd.length > 0) {
2552 MEMCPY(epd.value, p, epd.length);
2555 printer(arg,
"endpoint [%s]", epdisc_to_str(&epd));
2558 printer(arg,
"endpoint");
2564 while (p < optend) {
2566 printer(arg,
" %.2x", code);
2574 if (len > 0 && *p >=
' ' && *p < 0x7f) {
2576 ppp_print_string(p, len, printer, arg);
2587 printer(arg,
" magic=0x%x", cilong);
2596 printer(arg,
" magic=0x%x", cilong);
2599 if (code == TIMEREM) {
2603 printer(arg,
" seconds=%u", cilong);
2608 ppp_print_string(p, len, printer, arg);
2618 for (i = 0; i < len && i < 32; ++i) {
2620 printer(arg,
" %.2x", code);
2623 printer(arg,
" ...");
2635 static void LcpLinkFailure(fsm *f) {
2636 ppp_pcb *pcb = f->pcb;
2637 if (f->state == PPP_FSM_OPENED) {
2638 ppp_info(
"No response to %d echo-requests", pcb->lcp_echos_pending);
2639 ppp_notice(
"Serial link appears to be disconnected.");
2640 pcb->err_code = PPPERR_PEERDEAD;
2641 lcp_close(pcb,
"Peer not responding");
2649 static void LcpEchoCheck(fsm *f) {
2650 ppp_pcb *pcb = f->pcb;
2652 LcpSendEchoRequest (f);
2653 if (f->state != PPP_FSM_OPENED)
2659 if (pcb->lcp_echo_timer_running)
2660 ppp_warn(
"assertion lcp_echo_timer_running==0 failed");
2661 TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval);
2662 pcb->lcp_echo_timer_running = 1;
2669 static void LcpEchoTimeout(
void *arg) {
2671 ppp_pcb *pcb = f->pcb;
2672 if (pcb->lcp_echo_timer_running != 0) {
2673 pcb->lcp_echo_timer_running = 0;
2674 LcpEchoCheck ((fsm *) arg);
2682 static void lcp_received_echo_reply(fsm *f,
int id, u_char *inp,
int len) {
2683 ppp_pcb *pcb = f->pcb;
2684 lcp_options *go = &pcb->lcp_gotoptions;
2690 ppp_dbglog(
"lcp: received short Echo-Reply, length %d", len);
2693 GETLONG(magic_val, inp);
2694 if (go->neg_magicnumber
2695 && magic_val == go->magicnumber) {
2696 ppp_warn(
"appear to have received our own echo-reply!");
2701 pcb->lcp_echos_pending = 0;
2708 static void LcpSendEchoRequest(fsm *f) {
2709 ppp_pcb *pcb = f->pcb;
2710 lcp_options *go = &pcb->lcp_gotoptions;
2712 u_char pkt[4], *pktp;
2717 if (pcb->settings.lcp_echo_fails != 0) {
2718 if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) {
2720 pcb->lcp_echos_pending = 0;
2724 #if PPP_LCP_ADAPTIVE 2729 if (pcb->settings.lcp_echo_adaptive) {
2730 static unsigned int last_pkts_in = 0;
2732 #if PPP_STATS_SUPPORT 2733 update_link_stats(f->unit);
2734 link_stats_valid = 0;
2737 if (link_stats.pkts_in != last_pkts_in) {
2738 last_pkts_in = link_stats.pkts_in;
2747 if (f->state == PPP_FSM_OPENED) {
2748 lcp_magic = go->magicnumber;
2750 PUTLONG(lcp_magic, pktp);
2751 fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt);
2752 ++pcb->lcp_echos_pending;
2760 static void lcp_echo_lowerup(ppp_pcb *pcb) {
2761 fsm *f = &pcb->lcp_fsm;
2764 pcb->lcp_echos_pending = 0;
2765 pcb->lcp_echo_number = 0;
2766 pcb->lcp_echo_timer_running = 0;
2769 if (pcb->settings.lcp_echo_interval != 0)
2777 static void lcp_echo_lowerdown(ppp_pcb *pcb) {
2778 fsm *f = &pcb->lcp_fsm;
2780 if (pcb->lcp_echo_timer_running != 0) {
2781 UNTIMEOUT (LcpEchoTimeout, f);
2782 pcb->lcp_echo_timer_running = 0;
#define MEMCPY(dst, src, len)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
#define LWIP_UNUSED_ARG(x)