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
73static void lcp_delayed_up(
void *arg);
79int lcp_echo_interval = 0;
80int lcp_echo_fails = 0;
85static u_int lcp_echo_interval = LCP_ECHOINTERVAL;
86static u_int lcp_echo_fails = LCP_MAXECHOFAILS;
91bool lcp_echo_adaptive = 0;
98static int noopt (
char **);
102static int setendpoint (
char **);
103static void printendpoint (option_t *,
void (*)(
void *,
char *, ...),
108static 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 },
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 },
218static void lcp_resetci(fsm *f);
219static int lcp_cilen(fsm *f);
220static void lcp_addci(fsm *f, u_char *ucp,
int *lenp);
221static int lcp_ackci(fsm *f, u_char *p,
int len);
222static int lcp_nakci(fsm *f, u_char *p,
int len,
int treat_as_reject);
223static int lcp_rejci(fsm *f, u_char *p,
int len);
224static int lcp_reqci(fsm *f, u_char *inp,
int *lenp,
int reject_if_disagree);
225static void lcp_up(fsm *f);
226static void lcp_down(fsm *f);
227static void lcp_starting (fsm *);
228static void lcp_finished (fsm *);
229static int lcp_extcode(fsm *f,
int code,
int id, u_char *inp,
int len);
230static void lcp_rprotrej(fsm *f, u_char *inp,
int len);
236static void lcp_echo_lowerup(ppp_pcb *pcb);
237static void lcp_echo_lowerdown(ppp_pcb *pcb);
238static void LcpEchoTimeout(
void *arg);
239static void lcp_received_echo_reply(fsm *f,
int id, u_char *inp,
int len);
240static void LcpSendEchoRequest(fsm *f);
241static void LcpLinkFailure(fsm *f);
242static void LcpEchoCheck(fsm *f);
244static const fsm_callbacks lcp_callbacks = {
267static void lcp_init(ppp_pcb *pcb);
268static void lcp_input(ppp_pcb *pcb, u_char *p,
int len);
269static void lcp_protrej(ppp_pcb *pcb);
271static int lcp_printpkt(
const u_char *p,
int plen,
272 void (*printer) (
void *,
const char *, ...),
void *arg);
275const struct protent lcp_protent = {
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));
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);
351printendpoint(opt, printer, arg)
353 void (*printer) (
void *,
char *, ...);
356 printer(arg,
"%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));
363static 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;
406void 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;
422void lcp_close(ppp_pcb *pcb,
const char *reason) {
423 fsm *f = &pcb->lcp_fsm;
426 if (pcb->phase != PPP_PHASE_DEAD
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;
457void 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);
482void 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);
496static void lcp_delayed_up(
void *arg) {
499 if (f->flags & DELAYED_UP) {
500 f->flags &= ~DELAYED_UP;
509static 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);
523static 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);
562static 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);
620static void lcp_protrej(ppp_pcb *pcb) {
624 ppp_error(
"Received Protocol-Reject for LCP!");
625 fsm_protreject(&pcb->lcp_fsm);
632void lcp_sprotrej(ppp_pcb *pcb, u_char *p,
int len) {
633 fsm *f = &pcb->lcp_fsm;
643 fsm_sdata(f, PROTREJ, ++f->id,
651static 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();
754 go->neg_endpoint = 0;
758 if (pcb->settings.noendpoint)
759 ao->neg_endpoint = 0;
760 pcb->peer_mru = PPP_MRU;
770static 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) +
824 LENCISHORT(go->neg_mrru) +
826 LENCIVOID(go->neg_ssnhf) +
827 (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
834static 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);
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");
947static 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!"));
1127static 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!"));
1589static 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!"));
1820static 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)));
2290static 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);
2339static 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;
2358static void lcp_starting(fsm *f) {
2359 ppp_pcb *pcb = f->pcb;
2367static void lcp_finished(fsm *f) {
2368 ppp_pcb *pcb = f->pcb;
2369 link_terminated(pcb);
2377static const char*
const lcp_codenames[] = {
2378 "ConfReq",
"ConfAck",
"ConfNak",
"ConfRej",
2379 "TermReq",
"TermAck",
"CodeRej",
"ProtRej",
2380 "EchoReq",
"EchoRep",
"DiscReq",
"Ident",
2384static 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,
" ...");
2639static 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");
2653static 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;
2673static 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);
2686static 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;
2712static 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;
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;
2764static 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)
2781static 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;
#define LWIP_UNUSED_ARG(x)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)