1 /*
2 * lcp.c - PPP Link Control Protocol.
3 *
4 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. The name "Carnegie Mellon University" must not be used to
19 * endorse or promote products derived from this software without
20 * prior written permission. For permission or any legal
21 * details, please contact
22 * Office of Technology Transfer
23 * Carnegie Mellon University
24 * 5000 Forbes Avenue
25 * Pittsburgh, PA 15213-3890
26 * (412) 268-4387, fax: (412) 268-7395
27 * tech-transfer@andrew.cmu.edu
28 *
29 * 4. Redistributions of any form whatsoever must retain the following
30 * acknowledgment:
31 * "This product includes software developed by Computing Services
32 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33 *
34 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41 */
42
43 #include "netif/ppp/ppp_opts.h"
44 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
45
46 /*
47 * @todo:
48 */
49
50 #if 0 /* UNUSED */
51 #include <stdio.h>
52 #include <string.h>
53 #include <stdlib.h>
54 #endif /* UNUSED */
55
56 #include "netif/ppp/ppp_impl.h"
57
58 #include "netif/ppp/fsm.h"
59 #include "netif/ppp/lcp.h"
60 #if CHAP_SUPPORT
61 #include "netif/ppp/chap-new.h"
62 #endif /* CHAP_SUPPORT */
63 #include "netif/ppp/magic.h"
64
65 /*
66 * When the link comes up we want to be able to wait for a short while,
67 * or until seeing some input from the peer, before starting to send
68 * configure-requests. We do this by delaying the fsm_lowerup call.
69 */
70 /* steal a bit in fsm flags word */
71 #define DELAYED_UP 0x80
72
73 static void lcp_delayed_up(void *arg);
74
75 /*
76 * LCP-related command-line options.
77 */
78 #if 0 /* UNUSED */
79 int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
80 int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
81 #endif /* UNUSED */
82
83 #if 0 /* UNUSED */
84 /* options */
85 static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
86 static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
87 #endif /* UNUSED */
88
89 #if 0 /* UNUSED */
90 #if PPP_LCP_ADAPTIVE
91 bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */
92 #endif
93 bool lax_recv = 0; /* accept control chars in asyncmap */
94 bool noendpoint = 0; /* don't send/accept endpoint discriminator */
95 #endif /* UNUSED */
96
97 #if PPP_OPTIONS
98 static int noopt (char **);
99 #endif /* PPP_OPTIONS */
100
101 #ifdef HAVE_MULTILINK
102 static int setendpoint (char **);
103 static void printendpoint (option_t *, void (*)(void *, char *, ...),
104 void *);
105 #endif /* HAVE_MULTILINK */
106
107 #if PPP_OPTIONS
108 static option_t lcp_option_list[] = {
109 /* LCP options */
110 { "-all", o_special_noarg, (void *)noopt,
111 "Don't request/allow any LCP options" },
112
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 },
119
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 },
134
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 },
141
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 },
151
152 { "mtu", o_int, &lcp_allowoptions[0].mru,
153 "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
154
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 },
161
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 },
166
167 { "silent", o_bool, &lcp_wantoptions[0].silent,
168 "Set silent mode", 1 },
169
170 { "lcp-echo-failure", o_int, &lcp_echo_fails,
171 "Set number of consecutive echo failures to indicate link failure",
172 OPT_PRIO },
173 { "lcp-echo-interval", o_int, &lcp_echo_interval,
174 "Set time in seconds between LCP echo requests", OPT_PRIO },
175 #if PPP_LCP_ADAPTIVE
176 { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive,
177 "Suppress LCP echo requests if traffic was received", 1 },
178 #endif
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 },
187
188 { "receive-all", o_bool, &lax_recv,
189 "Accept all received control characters", 1 },
190
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 },
195
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 },
202
203 { "endpoint", o_special, (void *) setendpoint,
204 "Endpoint discriminator for multilink",
205 OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint },
206 #endif /* HAVE_MULTILINK */
207
208 { "noendpoint", o_bool, &noendpoint,
209 "Don't send or accept multilink endpoint discriminator", 1 },
210
211 {NULL}
212 };
213 #endif /* PPP_OPTIONS */
214
215 /*
216 * Callbacks for fsm code. (CI = Configuration Information)
217 */
218 static void lcp_resetci(fsm *f); /* Reset our CI */
219 static int lcp_cilen(fsm *f); /* Return length of our CI */
220 static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */
221 static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */
222 static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */
223 static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */
224 static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */
225 static void lcp_up(fsm *f); /* We're UP */
226 static void lcp_down(fsm *f); /* We're DOWN */
227 static void lcp_starting (fsm *); /* We need lower layer up */
228 static void lcp_finished (fsm *); /* We need lower layer down */
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);
231
232 /*
233 * routines to send LCP echos to peer
234 */
235
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);
243
244 static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */
245 lcp_resetci, /* Reset our Configuration Information */
246 lcp_cilen, /* Length of our Configuration Information */
247 lcp_addci, /* Add our Configuration Information */
248 lcp_ackci, /* ACK our Configuration Information */
249 lcp_nakci, /* NAK our Configuration Information */
250 lcp_rejci, /* Reject our Configuration Information */
251 lcp_reqci, /* Request peer's Configuration Information */
252 lcp_up, /* Called when fsm reaches OPENED state */
253 lcp_down, /* Called when fsm leaves OPENED state */
254 lcp_starting, /* Called when we want the lower layer up */
255 lcp_finished, /* Called when we want the lower layer down */
256 NULL, /* Called when Protocol-Reject received */
257 NULL, /* Retransmission is necessary */
258 lcp_extcode, /* Called to handle LCP-specific codes */
259 "LCP" /* String name of protocol */
260 };
261
262 /*
263 * Protocol entry points.
264 * Some of these are called directly.
265 */
266
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);
270 #if PRINTPKT_SUPPORT
271 static int lcp_printpkt(const u_char *p, int plen,
272 void (*printer) (void *, const char *, ...), void *arg);
273 #endif /* PRINTPKT_SUPPORT */
274
275 const struct protent lcp_protent = {
276 PPP_LCP,
277 lcp_init,
278 lcp_input,
279 lcp_protrej,
280 lcp_lowerup,
281 lcp_lowerdown,
282 lcp_open,
283 lcp_close,
284 #if PRINTPKT_SUPPORT
285 lcp_printpkt,
286 #endif /* PRINTPKT_SUPPORT */
287 #if PPP_DATAINPUT
288 NULL,
289 #endif /* PPP_DATAINPUT */
290 #if PRINTPKT_SUPPORT
291 "LCP",
292 NULL,
293 #endif /* PRINTPKT_SUPPORT */
294 #if PPP_OPTIONS
295 lcp_option_list,
296 NULL,
297 #endif /* PPP_OPTIONS */
298 #if DEMAND_SUPPORT
299 NULL,
300 NULL
301 #endif /* DEMAND_SUPPORT */
302 };
303
304 /*
305 * Length of each type of configuration option (in octets)
306 */
307 #define CILEN_VOID 2
308 #define CILEN_CHAR 3
309 #define CILEN_SHORT 4 /* CILEN_VOID + 2 */
310 #if CHAP_SUPPORT
311 #define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */
312 #endif /* CHAP_SUPPORT */
313 #define CILEN_LONG 6 /* CILEN_VOID + 4 */
314 #if LQR_SUPPORT
315 #define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */
316 #endif /* LQR_SUPPORT */
317 #define CILEN_CBCP 3
318
319 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
320 (x) == CONFNAK ? "NAK" : "REJ")
321
322 #if PPP_OPTIONS
323 /*
324 * noopt - Disable all options (why?).
325 */
326 static int
noopt(argv)327 noopt(argv)
328 char **argv;
329 {
330 BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
331 BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
332
333 return (1);
334 }
335 #endif /* PPP_OPTIONS */
336
337 #ifdef HAVE_MULTILINK
338 static int
setendpoint(argv)339 setendpoint(argv)
340 char **argv;
341 {
342 if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
343 lcp_wantoptions[0].neg_endpoint = 1;
344 return 1;
345 }
346 option_error("Can't parse '%s' as an endpoint discriminator", *argv);
347 return 0;
348 }
349
350 static void
printendpoint(opt,printer,arg)351 printendpoint(opt, printer, arg)
352 option_t *opt;
353 void (*printer) (void *, char *, ...);
354 void *arg;
355 {
356 printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));
357 }
358 #endif /* HAVE_MULTILINK */
359
360 /*
361 * lcp_init - Initialize LCP.
362 */
lcp_init(ppp_pcb * pcb)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;
367
368 f->pcb = pcb;
369 f->protocol = PPP_LCP;
370 f->callbacks = &lcp_callbacks;
371
372 fsm_init(f);
373
374 BZERO(wo, sizeof(*wo));
375 wo->neg_mru = 1;
376 wo->mru = PPP_MRU;
377 wo->neg_asyncmap = 1;
378 wo->neg_magicnumber = 1;
379 wo->neg_pcompression = 1;
380 wo->neg_accompression = 1;
381
382 BZERO(ao, sizeof(*ao));
383 ao->neg_mru = 1;
384 ao->mru = PPP_MAXMRU;
385 ao->neg_asyncmap = 1;
386 #if CHAP_SUPPORT
387 ao->neg_chap = 1;
388 ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED;
389 #endif /* CHAP_SUPPORT */
390 #if PAP_SUPPORT
391 ao->neg_upap = 1;
392 #endif /* PAP_SUPPORT */
393 #if EAP_SUPPORT
394 ao->neg_eap = 1;
395 #endif /* EAP_SUPPORT */
396 ao->neg_magicnumber = 1;
397 ao->neg_pcompression = 1;
398 ao->neg_accompression = 1;
399 ao->neg_endpoint = 1;
400 }
401
402
403 /*
404 * lcp_open - LCP is allowed to come up.
405 */
lcp_open(ppp_pcb * pcb)406 void lcp_open(ppp_pcb *pcb) {
407 fsm *f = &pcb->lcp_fsm;
408 lcp_options *wo = &pcb->lcp_wantoptions;
409
410 f->flags &= ~(OPT_PASSIVE | OPT_SILENT);
411 if (wo->passive)
412 f->flags |= OPT_PASSIVE;
413 if (wo->silent)
414 f->flags |= OPT_SILENT;
415 fsm_open(f);
416 }
417
418
419 /*
420 * lcp_close - Take LCP down.
421 */
lcp_close(ppp_pcb * pcb,const char * reason)422 void lcp_close(ppp_pcb *pcb, const char *reason) {
423 fsm *f = &pcb->lcp_fsm;
424 int oldstate;
425
426 if (pcb->phase != PPP_PHASE_DEAD
427 #ifdef HAVE_MULTILINK
428 && pcb->phase != PPP_PHASE_MASTER
429 #endif /* HAVE_MULTILINK */
430 )
431 new_phase(pcb, PPP_PHASE_TERMINATE);
432
433 if (f->flags & DELAYED_UP) {
434 UNTIMEOUT(lcp_delayed_up, f);
435 f->state = PPP_FSM_STOPPED;
436 }
437 oldstate = f->state;
438
439 fsm_close(f, reason);
440 if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) {
441 /*
442 * This action is not strictly according to the FSM in RFC1548,
443 * but it does mean that the program terminates if you do a
444 * lcp_close() when a connection hasn't been established
445 * because we are in passive/silent mode or because we have
446 * delayed the fsm_lowerup() call and it hasn't happened yet.
447 */
448 f->flags &= ~DELAYED_UP;
449 lcp_finished(f);
450 }
451 }
452
453
454 /*
455 * lcp_lowerup - The lower layer is up.
456 */
lcp_lowerup(ppp_pcb * pcb)457 void lcp_lowerup(ppp_pcb *pcb) {
458 lcp_options *wo = &pcb->lcp_wantoptions;
459 fsm *f = &pcb->lcp_fsm;
460 /*
461 * Don't use A/C or protocol compression on transmission,
462 * but accept A/C and protocol compressed packets
463 * if we are going to ask for A/C and protocol compression.
464 */
465 if (ppp_send_config(pcb, PPP_DEFMRU, 0xffffffff, 0, 0) < 0
466 || ppp_recv_config(pcb, PPP_DEFMRU, (pcb->settings.lax_recv? 0: 0xffffffff),
467 wo->neg_pcompression, wo->neg_accompression) < 0)
468 return;
469 pcb->peer_mru = PPP_DEFMRU;
470
471 if (pcb->settings.listen_time != 0) {
472 f->flags |= DELAYED_UP;
473 TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time);
474 } else
475 fsm_lowerup(f);
476 }
477
478
479 /*
480 * lcp_lowerdown - The lower layer is down.
481 */
lcp_lowerdown(ppp_pcb * pcb)482 void lcp_lowerdown(ppp_pcb *pcb) {
483 fsm *f = &pcb->lcp_fsm;
484
485 if (f->flags & DELAYED_UP) {
486 f->flags &= ~DELAYED_UP;
487 UNTIMEOUT(lcp_delayed_up, f);
488 } else
489 fsm_lowerdown(f);
490 }
491
492
493 /*
494 * lcp_delayed_up - Bring the lower layer up now.
495 */
lcp_delayed_up(void * arg)496 static void lcp_delayed_up(void *arg) {
497 fsm *f = (fsm*)arg;
498
499 if (f->flags & DELAYED_UP) {
500 f->flags &= ~DELAYED_UP;
501 fsm_lowerup(f);
502 }
503 }
504
505
506 /*
507 * lcp_input - Input LCP packet.
508 */
lcp_input(ppp_pcb * pcb,u_char * p,int len)509 static void lcp_input(ppp_pcb *pcb, u_char *p, int len) {
510 fsm *f = &pcb->lcp_fsm;
511
512 if (f->flags & DELAYED_UP) {
513 f->flags &= ~DELAYED_UP;
514 UNTIMEOUT(lcp_delayed_up, f);
515 fsm_lowerup(f);
516 }
517 fsm_input(f, p, len);
518 }
519
520 /*
521 * lcp_extcode - Handle a LCP-specific code.
522 */
lcp_extcode(fsm * f,int code,int id,u_char * inp,int 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;
526 u_char *magp;
527
528 switch( code ){
529 case PROTREJ:
530 lcp_rprotrej(f, inp, len);
531 break;
532
533 case ECHOREQ:
534 if (f->state != PPP_FSM_OPENED)
535 break;
536 magp = inp;
537 PUTLONG(go->magicnumber, magp);
538 fsm_sdata(f, ECHOREP, id, inp, len);
539 break;
540
541 case ECHOREP:
542 lcp_received_echo_reply(f, id, inp, len);
543 break;
544
545 case DISCREQ:
546 case IDENTIF:
547 case TIMEREM:
548 break;
549
550 default:
551 return 0;
552 }
553 return 1;
554 }
555
556
557 /*
558 * lcp_rprotrej - Receive an Protocol-Reject.
559 *
560 * Figure out which protocol is rejected and inform it.
561 */
lcp_rprotrej(fsm * f,u_char * inp,int len)562 static void lcp_rprotrej(fsm *f, u_char *inp, int len) {
563 int i;
564 const struct protent *protp;
565 u_short prot;
566 #if PPP_PROTOCOLNAME
567 const char *pname;
568 #endif /* PPP_PROTOCOLNAME */
569
570 if (len < 2) {
571 LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
572 return;
573 }
574
575 GETSHORT(prot, inp);
576
577 /*
578 * Protocol-Reject packets received in any state other than the LCP
579 * OPENED state SHOULD be silently discarded.
580 */
581 if( f->state != PPP_FSM_OPENED ){
582 LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state));
583 return;
584 }
585
586 #if PPP_PROTOCOLNAME
587 pname = protocol_name(prot);
588 #endif /* PPP_PROTOCOLNAME */
589
590 /*
591 * Upcall the proper Protocol-Reject routine.
592 */
593 for (i = 0; (protp = protocols[i]) != NULL; ++i)
594 if (protp->protocol == prot) {
595 #if PPP_PROTOCOLNAME
596 if (pname != NULL)
597 ppp_dbglog(("Protocol-Reject for '%s' (0x%x) received", pname,
598 prot));
599 else
600 #endif /* PPP_PROTOCOLNAME */
601 ppp_dbglog(("Protocol-Reject for 0x%x received", prot));
602 (*protp->protrej)(f->pcb);
603 return;
604 }
605
606 #if PPP_PROTOCOLNAME
607 if (pname != NULL)
608 ppp_warn(("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname,
609 prot));
610 else
611 #endif /* #if PPP_PROTOCOLNAME */
612 ppp_warn(("Protocol-Reject for unsupported protocol 0x%x", prot));
613 }
614
615
616 /*
617 * lcp_protrej - A Protocol-Reject was received.
618 */
619 /*ARGSUSED*/
lcp_protrej(ppp_pcb * pcb)620 static void lcp_protrej(ppp_pcb *pcb) {
621 /*
622 * Can't reject LCP!
623 */
624 ppp_error(("Received Protocol-Reject for LCP!"));
625 fsm_protreject(&pcb->lcp_fsm);
626 }
627
628
629 /*
630 * lcp_sprotrej - Send a Protocol-Reject for some protocol.
631 */
lcp_sprotrej(ppp_pcb * pcb,u_char * p,int len)632 void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) {
633 fsm *f = &pcb->lcp_fsm;
634 /*
635 * Send back the protocol and the information field of the
636 * rejected packet. We only get here if LCP is in the OPENED state.
637 */
638 #if 0
639 p += 2;
640 len -= 2;
641 #endif
642
643 fsm_sdata(f, PROTREJ, ++f->id,
644 p, len);
645 }
646
647
648 /*
649 * lcp_resetci - Reset our CI.
650 */
lcp_resetci(fsm * f)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;
656
657 #if PPP_AUTH_SUPPORT
658
659 /* note: default value is true for allow options */
660 if (pcb->settings.user && pcb->settings.passwd) {
661 #if PAP_SUPPORT
662 if (pcb->settings.refuse_pap) {
663 ao->neg_upap = 0;
664 }
665 #endif /* PAP_SUPPORT */
666 #if CHAP_SUPPORT
667 if (pcb->settings.refuse_chap) {
668 ao->chap_mdtype &= ~MDTYPE_MD5;
669 }
670 #if MSCHAP_SUPPORT
671 if (pcb->settings.refuse_mschap) {
672 ao->chap_mdtype &= ~MDTYPE_MICROSOFT;
673 }
674 if (pcb->settings.refuse_mschap_v2) {
675 ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2;
676 }
677 #endif /* MSCHAP_SUPPORT */
678 ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE);
679 #endif /* CHAP_SUPPORT */
680 #if EAP_SUPPORT
681 if (pcb->settings.refuse_eap) {
682 ao->neg_eap = 0;
683 }
684 #endif /* EAP_SUPPORT */
685
686 #if PPP_SERVER
687 /* note: default value is false for wanted options */
688 if (pcb->settings.auth_required) {
689 #if PAP_SUPPORT
690 if (!pcb->settings.refuse_pap) {
691 wo->neg_upap = 1;
692 }
693 #endif /* PAP_SUPPORT */
694 #if CHAP_SUPPORT
695 if (!pcb->settings.refuse_chap) {
696 wo->chap_mdtype |= MDTYPE_MD5;
697 }
698 #if MSCHAP_SUPPORT
699 if (!pcb->settings.refuse_mschap) {
700 wo->chap_mdtype |= MDTYPE_MICROSOFT;
701 }
702 if (!pcb->settings.refuse_mschap_v2) {
703 wo->chap_mdtype |= MDTYPE_MICROSOFT_V2;
704 }
705 #endif /* MSCHAP_SUPPORT */
706 wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE);
707 #endif /* CHAP_SUPPORT */
708 #if EAP_SUPPORT
709 if (!pcb->settings.refuse_eap) {
710 wo->neg_eap = 1;
711 }
712 #endif /* EAP_SUPPORT */
713 }
714 #endif /* PPP_SERVER */
715
716 } else {
717 #if PAP_SUPPORT
718 ao->neg_upap = 0;
719 #endif /* PAP_SUPPORT */
720 #if CHAP_SUPPORT
721 ao->neg_chap = 0;
722 ao->chap_mdtype = MDTYPE_NONE;
723 #endif /* CHAP_SUPPORT */
724 #if EAP_SUPPORT
725 ao->neg_eap = 0;
726 #endif /* EAP_SUPPORT */
727 }
728
729 PPPDEBUG(LOG_DEBUG, ("ppp: auth protocols:"));
730 #if PAP_SUPPORT
731 PPPDEBUG(LOG_DEBUG, (" PAP=%d", ao->neg_upap));
732 #endif /* PAP_SUPPORT */
733 #if CHAP_SUPPORT
734 PPPDEBUG(LOG_DEBUG, (" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5)));
735 #if MSCHAP_SUPPORT
736 PPPDEBUG(LOG_DEBUG, (" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2)));
737 #endif /* MSCHAP_SUPPORT */
738 #endif /* CHAP_SUPPORT */
739 #if EAP_SUPPORT
740 PPPDEBUG(LOG_DEBUG, (" EAP=%d", ao->neg_eap));
741 #endif /* EAP_SUPPORT */
742 PPPDEBUG(LOG_DEBUG, ("\n"));
743
744 #endif /* PPP_AUTH_SUPPORT */
745
746 wo->magicnumber = magic();
747 wo->numloops = 0;
748 *go = *wo;
749 #ifdef HAVE_MULTILINK
750 if (!multilink) {
751 go->neg_mrru = 0;
752 #endif /* HAVE_MULTILINK */
753 go->neg_ssnhf = 0;
754 go->neg_endpoint = 0;
755 #ifdef HAVE_MULTILINK
756 }
757 #endif /* HAVE_MULTILINK */
758 if (pcb->settings.noendpoint)
759 ao->neg_endpoint = 0;
760 pcb->peer_mru = PPP_DEFMRU;
761 #if 0 /* UNUSED */
762 auth_reset(pcb);
763 #endif /* UNUSED */
764 }
765
766
767 /*
768 * lcp_cilen - Return length of our CI.
769 */
lcp_cilen(fsm * f)770 static int lcp_cilen(fsm *f) {
771 ppp_pcb *pcb = f->pcb;
772 lcp_options *go = &pcb->lcp_gotoptions;
773
774 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
775 #if CHAP_SUPPORT
776 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
777 #endif /* CHAP_SUPPORT */
778 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
779 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
780 #if LQR_SUPPORT
781 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
782 #endif /* LQR_SUPPORT */
783 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
784 /*
785 * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will
786 * accept more than one. We prefer EAP first, then CHAP, then
787 * PAP.
788 */
789 return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) +
790 LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
791 #if EAP_SUPPORT
792 LENCISHORT(go->neg_eap) +
793 #endif /* EAP_SUPPORT */
794 #if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */
795 #if EAP_SUPPORT
796 LENCICHAP(!go->neg_eap && go->neg_chap) +
797 #endif /* EAP_SUPPORT */
798 #if !EAP_SUPPORT
799 LENCICHAP(go->neg_chap) +
800 #endif /* !EAP_SUPPORT */
801 #endif /* CHAP_SUPPORT */
802 #if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */
803 #if EAP_SUPPORT && CHAP_SUPPORT
804 LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) +
805 #endif /* EAP_SUPPORT && CHAP_SUPPORT */
806 #if EAP_SUPPORT && !CHAP_SUPPORT
807 LENCISHORT(!go->neg_eap && go->neg_upap) +
808 #endif /* EAP_SUPPORT && !CHAP_SUPPORT */
809 #if !EAP_SUPPORT && CHAP_SUPPORT
810 LENCISHORT(!go->neg_chap && go->neg_upap) +
811 #endif /* !EAP_SUPPORT && CHAP_SUPPORT */
812 #if !EAP_SUPPORT && !CHAP_SUPPORT
813 LENCISHORT(go->neg_upap) +
814 #endif /* !EAP_SUPPORT && !CHAP_SUPPORT */
815 #endif /* PAP_SUPPORT */
816 #if LQR_SUPPORT
817 LENCILQR(go->neg_lqr) +
818 #endif /* LQR_SUPPORT */
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) +
825 #endif /* HAVE_MULTILINK */
826 LENCIVOID(go->neg_ssnhf) +
827 (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
828 }
829
830
831 /*
832 * lcp_addci - Add our desired CIs to a packet.
833 */
lcp_addci(fsm * f,u_char * ucp,int * lenp)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;
838
839 #define ADDCIVOID(opt, neg) \
840 if (neg) { \
841 PUTCHAR(opt, ucp); \
842 PUTCHAR(CILEN_VOID, ucp); \
843 }
844 #define ADDCISHORT(opt, neg, val) \
845 if (neg) { \
846 PUTCHAR(opt, ucp); \
847 PUTCHAR(CILEN_SHORT, ucp); \
848 PUTSHORT(val, ucp); \
849 }
850 #if CHAP_SUPPORT
851 #define ADDCICHAP(opt, neg, val) \
852 if (neg) { \
853 PUTCHAR((opt), ucp); \
854 PUTCHAR(CILEN_CHAP, ucp); \
855 PUTSHORT(PPP_CHAP, ucp); \
856 PUTCHAR((CHAP_DIGEST(val)), ucp); \
857 }
858 #endif /* CHAP_SUPPORT */
859 #define ADDCILONG(opt, neg, val) \
860 if (neg) { \
861 PUTCHAR(opt, ucp); \
862 PUTCHAR(CILEN_LONG, ucp); \
863 PUTLONG(val, ucp); \
864 }
865 #if LQR_SUPPORT
866 #define ADDCILQR(opt, neg, val) \
867 if (neg) { \
868 PUTCHAR(opt, ucp); \
869 PUTCHAR(CILEN_LQR, ucp); \
870 PUTSHORT(PPP_LQR, ucp); \
871 PUTLONG(val, ucp); \
872 }
873 #endif /* LQR_SUPPORT */
874 #define ADDCICHAR(opt, neg, val) \
875 if (neg) { \
876 PUTCHAR(opt, ucp); \
877 PUTCHAR(CILEN_CHAR, ucp); \
878 PUTCHAR(val, ucp); \
879 }
880 #define ADDCIENDP(opt, neg, class, val, len) \
881 if (neg) { \
882 int i; \
883 PUTCHAR(opt, ucp); \
884 PUTCHAR(CILEN_CHAR + len, ucp); \
885 PUTCHAR(class, ucp); \
886 for (i = 0; i < len; ++i) \
887 PUTCHAR(val[i], ucp); \
888 }
889
890 ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
891 ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
892 go->asyncmap);
893 #if EAP_SUPPORT
894 ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
895 #endif /* EAP_SUPPORT */
896 #if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */
897 #if EAP_SUPPORT
898 ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
899 #endif /* EAP_SUPPORT */
900 #if !EAP_SUPPORT
901 ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
902 #endif /* !EAP_SUPPORT */
903 #endif /* CHAP_SUPPORT */
904 #if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */
905 #if EAP_SUPPORT && CHAP_SUPPORT
906 ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP);
907 #endif /* EAP_SUPPORT && CHAP_SUPPORT */
908 #if EAP_SUPPORT && !CHAP_SUPPORT
909 ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP);
910 #endif /* EAP_SUPPORT && !CHAP_SUPPORT */
911 #if !EAP_SUPPORT && CHAP_SUPPORT
912 ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
913 #endif /* !EAP_SUPPORT && CHAP_SUPPORT */
914 #if !EAP_SUPPORT && !CHAP_SUPPORT
915 ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP);
916 #endif /* !EAP_SUPPORT && !CHAP_SUPPORT */
917 #endif /* PAP_SUPPORT */
918 #if LQR_SUPPORT
919 ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
920 #endif /* LQR_SUPPORT */
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);
927 #endif
928 ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
929 ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_,
930 go->endpoint.value, go->endpoint.length);
931
932 if (ucp - start_ucp != *lenp) {
933 /* this should never happen, because peer_mtu should be 1500 */
934 ppp_error(("Bug in lcp_addci: wrong length"));
935 }
936 }
937
938
939 /*
940 * lcp_ackci - Ack our CIs.
941 * This should not modify any state if the Ack is bad.
942 *
943 * Returns:
944 * 0 - Ack was bad.
945 * 1 - Ack was good.
946 */
lcp_ackci(fsm * f,u_char * p,int len)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;
951 u_short cishort;
952 u32_t cilong;
953
954 /*
955 * CIs must be in exactly the same order that we sent.
956 * Check packet length and CI length at each step.
957 * If we find any deviations, then this packet is bad.
958 */
959 #define ACKCIVOID(opt, neg) \
960 if (neg) { \
961 if ((len -= CILEN_VOID) < 0) \
962 goto bad; \
963 GETCHAR(citype, p); \
964 GETCHAR(cilen, p); \
965 if (cilen != CILEN_VOID || \
966 citype != opt) \
967 goto bad; \
968 }
969 #define ACKCISHORT(opt, neg, val) \
970 if (neg) { \
971 if ((len -= CILEN_SHORT) < 0) \
972 goto bad; \
973 GETCHAR(citype, p); \
974 GETCHAR(cilen, p); \
975 if (cilen != CILEN_SHORT || \
976 citype != opt) \
977 goto bad; \
978 GETSHORT(cishort, p); \
979 if (cishort != val) \
980 goto bad; \
981 }
982 #define ACKCICHAR(opt, neg, val) \
983 if (neg) { \
984 if ((len -= CILEN_CHAR) < 0) \
985 goto bad; \
986 GETCHAR(citype, p); \
987 GETCHAR(cilen, p); \
988 if (cilen != CILEN_CHAR || \
989 citype != opt) \
990 goto bad; \
991 GETCHAR(cichar, p); \
992 if (cichar != val) \
993 goto bad; \
994 }
995 #if CHAP_SUPPORT
996 #define ACKCICHAP(opt, neg, val) \
997 if (neg) { \
998 if ((len -= CILEN_CHAP) < 0) \
999 goto bad; \
1000 GETCHAR(citype, p); \
1001 GETCHAR(cilen, p); \
1002 if (cilen != CILEN_CHAP || \
1003 citype != (opt)) \
1004 goto bad; \
1005 GETSHORT(cishort, p); \
1006 if (cishort != PPP_CHAP) \
1007 goto bad; \
1008 GETCHAR(cichar, p); \
1009 if (cichar != (CHAP_DIGEST(val))) \
1010 goto bad; \
1011 }
1012 #endif /* CHAP_SUPPORT */
1013 #define ACKCILONG(opt, neg, val) \
1014 if (neg) { \
1015 if ((len -= CILEN_LONG) < 0) \
1016 goto bad; \
1017 GETCHAR(citype, p); \
1018 GETCHAR(cilen, p); \
1019 if (cilen != CILEN_LONG || \
1020 citype != opt) \
1021 goto bad; \
1022 GETLONG(cilong, p); \
1023 if (cilong != val) \
1024 goto bad; \
1025 }
1026 #if LQR_SUPPORT
1027 #define ACKCILQR(opt, neg, val) \
1028 if (neg) { \
1029 if ((len -= CILEN_LQR) < 0) \
1030 goto bad; \
1031 GETCHAR(citype, p); \
1032 GETCHAR(cilen, p); \
1033 if (cilen != CILEN_LQR || \
1034 citype != opt) \
1035 goto bad; \
1036 GETSHORT(cishort, p); \
1037 if (cishort != PPP_LQR) \
1038 goto bad; \
1039 GETLONG(cilong, p); \
1040 if (cilong != val) \
1041 goto bad; \
1042 }
1043 #endif /* LQR_SUPPORT */
1044 #define ACKCIENDP(opt, neg, class, val, vlen) \
1045 if (neg) { \
1046 int i; \
1047 if ((len -= CILEN_CHAR + vlen) < 0) \
1048 goto bad; \
1049 GETCHAR(citype, p); \
1050 GETCHAR(cilen, p); \
1051 if (cilen != CILEN_CHAR + vlen || \
1052 citype != opt) \
1053 goto bad; \
1054 GETCHAR(cichar, p); \
1055 if (cichar != class) \
1056 goto bad; \
1057 for (i = 0; i < vlen; ++i) { \
1058 GETCHAR(cichar, p); \
1059 if (cichar != val[i]) \
1060 goto bad; \
1061 } \
1062 }
1063
1064 ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
1065 ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
1066 go->asyncmap);
1067 #if EAP_SUPPORT
1068 ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
1069 #endif /* EAP_SUPPORT */
1070 #if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */
1071 #if EAP_SUPPORT
1072 ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
1073 #endif /* EAP_SUPPORT */
1074 #if !EAP_SUPPORT
1075 ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
1076 #endif /* !EAP_SUPPORT */
1077 #endif /* CHAP_SUPPORT */
1078 #if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */
1079 #if EAP_SUPPORT && CHAP_SUPPORT
1080 ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP);
1081 #endif /* EAP_SUPPORT && CHAP_SUPPORT */
1082 #if EAP_SUPPORT && !CHAP_SUPPORT
1083 ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP);
1084 #endif /* EAP_SUPPORT && !CHAP_SUPPORT */
1085 #if !EAP_SUPPORT && CHAP_SUPPORT
1086 ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
1087 #endif /* !EAP_SUPPORT && CHAP_SUPPORT */
1088 #if !EAP_SUPPORT && !CHAP_SUPPORT
1089 ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP);
1090 #endif /* !EAP_SUPPORT && !CHAP_SUPPORT */
1091 #endif /* PAP_SUPPORT */
1092 #if LQR_SUPPORT
1093 ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1094 #endif /* LQR_SUPPORT */
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);
1101 #endif /* HAVE_MULTILINK */
1102 ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
1103 ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_,
1104 go->endpoint.value, go->endpoint.length);
1105
1106 /*
1107 * If there are any remaining CIs, then this packet is bad.
1108 */
1109 if (len != 0)
1110 goto bad;
1111 return (1);
1112 bad:
1113 LCPDEBUG(("lcp_acki: received bad Ack!"));
1114 return (0);
1115 }
1116
1117
1118 /*
1119 * lcp_nakci - Peer has sent a NAK for some of our CIs.
1120 * This should not modify any state if the Nak is bad
1121 * or if LCP is in the OPENED state.
1122 *
1123 * Returns:
1124 * 0 - Nak was bad.
1125 * 1 - Nak was good.
1126 */
lcp_nakci(fsm * f,u_char * p,int len,int treat_as_reject)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;
1132 u_short cishort;
1133 u32_t cilong;
1134 lcp_options no; /* options we've seen Naks for */
1135 lcp_options try_; /* options to request next time */
1136 int looped_back = 0;
1137 int cilen;
1138
1139 BZERO(&no, sizeof(no));
1140 try_ = *go;
1141
1142 /*
1143 * Any Nak'd CIs must be in exactly the same order that we sent.
1144 * Check packet length and CI length at each step.
1145 * If we find any deviations, then this packet is bad.
1146 */
1147 #define NAKCIVOID(opt, neg) \
1148 if (go->neg && \
1149 len >= CILEN_VOID && \
1150 p[1] == CILEN_VOID && \
1151 p[0] == opt) { \
1152 len -= CILEN_VOID; \
1153 INCPTR(CILEN_VOID, p); \
1154 no.neg = 1; \
1155 try_.neg = 0; \
1156 }
1157 #if CHAP_SUPPORT
1158 #define NAKCICHAP(opt, neg, code) \
1159 if (go->neg && \
1160 len >= CILEN_CHAP && \
1161 p[1] == CILEN_CHAP && \
1162 p[0] == opt) { \
1163 len -= CILEN_CHAP; \
1164 INCPTR(2, p); \
1165 GETSHORT(cishort, p); \
1166 GETCHAR(cichar, p); \
1167 no.neg = 1; \
1168 code \
1169 }
1170 #endif /* CHAP_SUPPORT */
1171 #define NAKCICHAR(opt, neg, code) \
1172 if (go->neg && \
1173 len >= CILEN_CHAR && \
1174 p[1] == CILEN_CHAR && \
1175 p[0] == opt) { \
1176 len -= CILEN_CHAR; \
1177 INCPTR(2, p); \
1178 GETCHAR(cichar, p); \
1179 no.neg = 1; \
1180 code \
1181 }
1182 #define NAKCISHORT(opt, neg, code) \
1183 if (go->neg && \
1184 len >= CILEN_SHORT && \
1185 p[1] == CILEN_SHORT && \
1186 p[0] == opt) { \
1187 len -= CILEN_SHORT; \
1188 INCPTR(2, p); \
1189 GETSHORT(cishort, p); \
1190 no.neg = 1; \
1191 code \
1192 }
1193 #define NAKCILONG(opt, neg, code) \
1194 if (go->neg && \
1195 len >= CILEN_LONG && \
1196 p[1] == CILEN_LONG && \
1197 p[0] == opt) { \
1198 len -= CILEN_LONG; \
1199 INCPTR(2, p); \
1200 GETLONG(cilong, p); \
1201 no.neg = 1; \
1202 code \
1203 }
1204 #if LQR_SUPPORT
1205 #define NAKCILQR(opt, neg, code) \
1206 if (go->neg && \
1207 len >= CILEN_LQR && \
1208 p[1] == CILEN_LQR && \
1209 p[0] == opt) { \
1210 len -= CILEN_LQR; \
1211 INCPTR(2, p); \
1212 GETSHORT(cishort, p); \
1213 GETLONG(cilong, p); \
1214 no.neg = 1; \
1215 code \
1216 }
1217 #endif /* LQR_SUPPORT */
1218 #define NAKCIENDP(opt, neg) \
1219 if (go->neg && \
1220 len >= CILEN_CHAR && \
1221 p[0] == opt && \
1222 p[1] >= CILEN_CHAR && \
1223 p[1] <= len) { \
1224 len -= p[1]; \
1225 INCPTR(p[1], p); \
1226 no.neg = 1; \
1227 try_.neg = 0; \
1228 }
1229
1230 /*
1231 * NOTE! There must be no assignments to individual fields of *go in
1232 * the code below. Any such assignment is a BUG!
1233 */
1234 /*
1235 * We don't care if they want to send us smaller packets than
1236 * we want. Therefore, accept any MRU less than what we asked for,
1237 * but then ignore the new value when setting the MRU in the kernel.
1238 * If they send us a bigger MRU than what we asked, accept it, up to
1239 * the limit of the default MRU we'd get if we didn't negotiate.
1240 */
1241 if (go->neg_mru && go->mru != PPP_DEFMRU) {
1242 NAKCISHORT(CI_MRU, neg_mru,
1243 if (cishort <= wo->mru || cishort <= PPP_DEFMRU)
1244 try_.mru = cishort;
1245 );
1246 }
1247
1248 /*
1249 * Add any characters they want to our (receive-side) asyncmap.
1250 */
1251 if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
1252 NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
1253 try_.asyncmap = go->asyncmap | cilong;
1254 );
1255 }
1256
1257 /*
1258 * If they've nak'd our authentication-protocol, check whether
1259 * they are proposing a different protocol, or a different
1260 * hash algorithm for CHAP.
1261 */
1262 if ((0
1263 #if CHAP_SUPPORT
1264 || go->neg_chap
1265 #endif /* CHAP_SUPPORT */
1266 #if PAP_SUPPORT
1267 || go->neg_upap
1268 #endif /* PAP_SUPPORT */
1269 #if EAP_SUPPORT
1270 || go->neg_eap
1271 #endif /* EAP_SUPPORT */
1272 )
1273 && len >= CILEN_SHORT
1274 && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
1275 cilen = p[1];
1276 len -= cilen;
1277 #if CHAP_SUPPORT
1278 no.neg_chap = go->neg_chap;
1279 #endif /* CHAP_SUPPORT */
1280 #if PAP_SUPPORT
1281 no.neg_upap = go->neg_upap;
1282 #endif /* PAP_SUPPORT */
1283 #if EAP_SUPPORT
1284 no.neg_eap = go->neg_eap;
1285 #endif /* EAP_SUPPORT */
1286 INCPTR(2, p);
1287 GETSHORT(cishort, p);
1288
1289 #if PAP_SUPPORT
1290 if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
1291 #if EAP_SUPPORT
1292 /* If we were asking for EAP, then we need to stop that. */
1293 if (go->neg_eap)
1294 try_.neg_eap = 0;
1295 else
1296 #endif /* EAP_SUPPORT */
1297
1298 #if CHAP_SUPPORT
1299 /* If we were asking for CHAP, then we need to stop that. */
1300 if (go->neg_chap)
1301 try_.neg_chap = 0;
1302 else
1303 #endif /* CHAP_SUPPORT */
1304
1305 /*
1306 * If we weren't asking for CHAP or EAP, then we were asking for
1307 * PAP, in which case this Nak is bad.
1308 */
1309 goto bad;
1310 } else
1311 #endif /* PAP_SUPPORT */
1312
1313 #if CHAP_SUPPORT
1314 if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
1315 GETCHAR(cichar, p);
1316 #if EAP_SUPPORT
1317 /* Stop asking for EAP, if we were. */
1318 if (go->neg_eap) {
1319 try_.neg_eap = 0;
1320 /* Try to set up to use their suggestion, if possible */
1321 if (CHAP_CANDIGEST(go->chap_mdtype, cichar))
1322 try_.chap_mdtype = CHAP_MDTYPE_D(cichar);
1323 } else
1324 #endif /* EAP_SUPPORT */
1325 if (go->neg_chap) {
1326 /*
1327 * We were asking for our preferred algorithm, they must
1328 * want something different.
1329 */
1330 if (cichar != CHAP_DIGEST(go->chap_mdtype)) {
1331 if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) {
1332 /* Use their suggestion if we support it ... */
1333 try_.chap_mdtype = CHAP_MDTYPE_D(cichar);
1334 } else {
1335 /* ... otherwise, try our next-preferred algorithm. */
1336 try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype));
1337 if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */
1338 try_.neg_chap = 0;
1339 }
1340 } else {
1341 /*
1342 * Whoops, they Nak'd our algorithm of choice
1343 * but then suggested it back to us.
1344 */
1345 goto bad;
1346 }
1347 } else {
1348 /*
1349 * Stop asking for PAP if we were asking for it.
1350 */
1351 #if PAP_SUPPORT
1352 try_.neg_upap = 0;
1353 #endif /* PAP_SUPPORT */
1354 }
1355
1356 } else
1357 #endif /* CHAP_SUPPORT */
1358 {
1359
1360 #if EAP_SUPPORT
1361 /*
1362 * If we were asking for EAP, and they're Conf-Naking EAP,
1363 * well, that's just strange. Nobody should do that.
1364 */
1365 if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap)
1366 ppp_dbglog(("Unexpected Conf-Nak for EAP"));
1367
1368 /*
1369 * We don't recognize what they're suggesting.
1370 * Stop asking for what we were asking for.
1371 */
1372 if (go->neg_eap)
1373 try_.neg_eap = 0;
1374 else
1375 #endif /* EAP_SUPPORT */
1376
1377 #if CHAP_SUPPORT
1378 if (go->neg_chap)
1379 try_.neg_chap = 0;
1380 else
1381 #endif /* CHAP_SUPPORT */
1382
1383 #if PAP_SUPPORT
1384 if(1)
1385 try_.neg_upap = 0;
1386 else
1387 #endif /* PAP_SUPPORT */
1388 {}
1389
1390 p += cilen - CILEN_SHORT;
1391 }
1392 }
1393
1394 #if LQR_SUPPORT
1395 /*
1396 * If they can't cope with our link quality protocol, we'll have
1397 * to stop asking for LQR. We haven't got any other protocol.
1398 * If they Nak the reporting period, take their value XXX ?
1399 */
1400 NAKCILQR(CI_QUALITY, neg_lqr,
1401 if (cishort != PPP_LQR)
1402 try_.neg_lqr = 0;
1403 else
1404 try_.lqr_period = cilong;
1405 );
1406 #endif /* LQR_SUPPORT */
1407
1408 /*
1409 * Only implementing CBCP...not the rest of the callback options
1410 */
1411 NAKCICHAR(CI_CALLBACK, neg_cbcp,
1412 try_.neg_cbcp = 0;
1413 (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */
1414 );
1415
1416 /*
1417 * Check for a looped-back line.
1418 */
1419 NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1420 try_.magicnumber = magic();
1421 looped_back = 1;
1422 );
1423
1424 /*
1425 * Peer shouldn't send Nak for protocol compression or
1426 * address/control compression requests; they should send
1427 * a Reject instead. If they send a Nak, treat it as a Reject.
1428 */
1429 NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1430 NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1431
1432 #ifdef HAVE_MULTILINK
1433 /*
1434 * Nak for MRRU option - accept their value if it is smaller
1435 * than the one we want.
1436 */
1437 if (go->neg_mrru) {
1438 NAKCISHORT(CI_MRRU, neg_mrru,
1439 if (treat_as_reject)
1440 try_.neg_mrru = 0;
1441 else if (cishort <= wo->mrru)
1442 try_.mrru = cishort;
1443 );
1444 }
1445 #else /* HAVE_MULTILINK */
1446 LWIP_UNUSED_ARG(treat_as_reject);
1447 #endif /* HAVE_MULTILINK */
1448
1449 /*
1450 * Nak for short sequence numbers shouldn't be sent, treat it
1451 * like a reject.
1452 */
1453 NAKCIVOID(CI_SSNHF, neg_ssnhf);
1454
1455 /*
1456 * Nak of the endpoint discriminator option is not permitted,
1457 * treat it like a reject.
1458 */
1459 NAKCIENDP(CI_EPDISC, neg_endpoint);
1460
1461 /*
1462 * There may be remaining CIs, if the peer is requesting negotiation
1463 * on an option that we didn't include in our request packet.
1464 * If we see an option that we requested, or one we've already seen
1465 * in this packet, then this packet is bad.
1466 * If we wanted to respond by starting to negotiate on the requested
1467 * option(s), we could, but we don't, because except for the
1468 * authentication type and quality protocol, if we are not negotiating
1469 * an option, it is because we were told not to.
1470 * For the authentication type, the Nak from the peer means
1471 * `let me authenticate myself with you' which is a bit pointless.
1472 * For the quality protocol, the Nak means `ask me to send you quality
1473 * reports', but if we didn't ask for them, we don't want them.
1474 * An option we don't recognize represents the peer asking to
1475 * negotiate some option we don't support, so ignore it.
1476 */
1477 while (len >= CILEN_VOID) {
1478 GETCHAR(citype, p);
1479 GETCHAR(cilen, p);
1480 if (cilen < CILEN_VOID || (len -= cilen) < 0)
1481 goto bad;
1482 next = p + cilen - 2;
1483
1484 switch (citype) {
1485 case CI_MRU:
1486 if ((go->neg_mru && go->mru != PPP_DEFMRU)
1487 || no.neg_mru || cilen != CILEN_SHORT)
1488 goto bad;
1489 GETSHORT(cishort, p);
1490 if (cishort < PPP_DEFMRU) {
1491 try_.neg_mru = 1;
1492 try_.mru = cishort;
1493 }
1494 break;
1495 case CI_ASYNCMAP:
1496 if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1497 || no.neg_asyncmap || cilen != CILEN_LONG)
1498 goto bad;
1499 break;
1500 case CI_AUTHTYPE:
1501 /* This is potentially dead code (#if !PPP_AUTH_SUPPORT)
1502 * Thus the double parantheses to mark the code explicitely
1503 * disabled when building with clang
1504 */
1505 if ((0
1506 #if CHAP_SUPPORT
1507 || go->neg_chap || no.neg_chap
1508 #endif /* CHAP_SUPPORT */
1509 #if PAP_SUPPORT
1510 || go->neg_upap || no.neg_upap
1511 #endif /* PAP_SUPPORT */
1512 #if EAP_SUPPORT
1513 || go->neg_eap || no.neg_eap
1514 #endif /* EAP_SUPPORT */
1515 ))
1516 goto bad;
1517 break;
1518 case CI_MAGICNUMBER:
1519 if (go->neg_magicnumber || no.neg_magicnumber ||
1520 cilen != CILEN_LONG)
1521 goto bad;
1522 break;
1523 case CI_PCOMPRESSION:
1524 if (go->neg_pcompression || no.neg_pcompression
1525 || cilen != CILEN_VOID)
1526 goto bad;
1527 break;
1528 case CI_ACCOMPRESSION:
1529 if (go->neg_accompression || no.neg_accompression
1530 || cilen != CILEN_VOID)
1531 goto bad;
1532 break;
1533 #if LQR_SUPPORT
1534 case CI_QUALITY:
1535 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1536 goto bad;
1537 break;
1538 #endif /* LQR_SUPPORT */
1539 #ifdef HAVE_MULTILINK
1540 case CI_MRRU:
1541 if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1542 goto bad;
1543 break;
1544 #endif /* HAVE_MULTILINK */
1545 case CI_SSNHF:
1546 if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1547 goto bad;
1548 try_.neg_ssnhf = 1;
1549 break;
1550 case CI_EPDISC:
1551 if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1552 goto bad;
1553 break;
1554 default:
1555 break;
1556 }
1557 p = next;
1558 }
1559
1560 /*
1561 * OK, the Nak is good. Now we can update state.
1562 * If there are any options left we ignore them.
1563 */
1564 if (f->state != PPP_FSM_OPENED) {
1565 if (looped_back) {
1566 if (++try_.numloops >= pcb->settings.lcp_loopbackfail) {
1567 ppp_notice(("Serial line is looped back."));
1568 pcb->err_code = PPPERR_LOOPBACK;
1569 lcp_close(f->pcb, "Loopback detected");
1570 }
1571 } else
1572 try_.numloops = 0;
1573 *go = try_;
1574 }
1575
1576 return 1;
1577
1578 bad:
1579 LCPDEBUG(("lcp_nakci: received bad Nak!"));
1580 return 0;
1581 }
1582
1583
1584 /*
1585 * lcp_rejci - Peer has Rejected some of our CIs.
1586 * This should not modify any state if the Reject is bad
1587 * or if LCP is in the OPENED state.
1588 *
1589 * Returns:
1590 * 0 - Reject was bad.
1591 * 1 - Reject was good.
1592 */
lcp_rejci(fsm * f,u_char * p,int len)1593 static int lcp_rejci(fsm *f, u_char *p, int len) {
1594 ppp_pcb *pcb = f->pcb;
1595 lcp_options *go = &pcb->lcp_gotoptions;
1596 u_char cichar;
1597 u_short cishort;
1598 u32_t cilong;
1599 lcp_options try_; /* options to request next time */
1600
1601 try_ = *go;
1602
1603 /*
1604 * Any Rejected CIs must be in exactly the same order that we sent.
1605 * Check packet length and CI length at each step.
1606 * If we find any deviations, then this packet is bad.
1607 */
1608 #define REJCIVOID(opt, neg) \
1609 if (go->neg && \
1610 len >= CILEN_VOID && \
1611 p[1] == CILEN_VOID && \
1612 p[0] == opt) { \
1613 len -= CILEN_VOID; \
1614 INCPTR(CILEN_VOID, p); \
1615 try_.neg = 0; \
1616 }
1617 #define REJCISHORT(opt, neg, val) \
1618 if (go->neg && \
1619 len >= CILEN_SHORT && \
1620 p[1] == CILEN_SHORT && \
1621 p[0] == opt) { \
1622 len -= CILEN_SHORT; \
1623 INCPTR(2, p); \
1624 GETSHORT(cishort, p); \
1625 /* Check rejected value. */ \
1626 if (cishort != val) \
1627 goto bad; \
1628 try_.neg = 0; \
1629 }
1630
1631 #if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT
1632 #define REJCICHAP(opt, neg, val) \
1633 if (go->neg && \
1634 len >= CILEN_CHAP && \
1635 p[1] == CILEN_CHAP && \
1636 p[0] == opt) { \
1637 len -= CILEN_CHAP; \
1638 INCPTR(2, p); \
1639 GETSHORT(cishort, p); \
1640 GETCHAR(cichar, p); \
1641 /* Check rejected value. */ \
1642 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1643 goto bad; \
1644 try_.neg = 0; \
1645 try_.neg_eap = try_.neg_upap = 0; \
1646 }
1647 #endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */
1648
1649 #if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT
1650 #define REJCICHAP(opt, neg, val) \
1651 if (go->neg && \
1652 len >= CILEN_CHAP && \
1653 p[1] == CILEN_CHAP && \
1654 p[0] == opt) { \
1655 len -= CILEN_CHAP; \
1656 INCPTR(2, p); \
1657 GETSHORT(cishort, p); \
1658 GETCHAR(cichar, p); \
1659 /* Check rejected value. */ \
1660 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1661 goto bad; \
1662 try_.neg = 0; \
1663 try_.neg_upap = 0; \
1664 }
1665 #endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */
1666
1667 #if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT
1668 #define REJCICHAP(opt, neg, val) \
1669 if (go->neg && \
1670 len >= CILEN_CHAP && \
1671 p[1] == CILEN_CHAP && \
1672 p[0] == opt) { \
1673 len -= CILEN_CHAP; \
1674 INCPTR(2, p); \
1675 GETSHORT(cishort, p); \
1676 GETCHAR(cichar, p); \
1677 /* Check rejected value. */ \
1678 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1679 goto bad; \
1680 try_.neg = 0; \
1681 try_.neg_eap = 0; \
1682 }
1683 #endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */
1684
1685 #if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT
1686 #define REJCICHAP(opt, neg, val) \
1687 if (go->neg && \
1688 len >= CILEN_CHAP && \
1689 p[1] == CILEN_CHAP && \
1690 p[0] == opt) { \
1691 len -= CILEN_CHAP; \
1692 INCPTR(2, p); \
1693 GETSHORT(cishort, p); \
1694 GETCHAR(cichar, p); \
1695 /* Check rejected value. */ \
1696 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1697 goto bad; \
1698 try_.neg = 0; \
1699 }
1700 #endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */
1701
1702 #define REJCILONG(opt, neg, val) \
1703 if (go->neg && \
1704 len >= CILEN_LONG && \
1705 p[1] == CILEN_LONG && \
1706 p[0] == opt) { \
1707 len -= CILEN_LONG; \
1708 INCPTR(2, p); \
1709 GETLONG(cilong, p); \
1710 /* Check rejected value. */ \
1711 if (cilong != val) \
1712 goto bad; \
1713 try_.neg = 0; \
1714 }
1715 #if LQR_SUPPORT
1716 #define REJCILQR(opt, neg, val) \
1717 if (go->neg && \
1718 len >= CILEN_LQR && \
1719 p[1] == CILEN_LQR && \
1720 p[0] == opt) { \
1721 len -= CILEN_LQR; \
1722 INCPTR(2, p); \
1723 GETSHORT(cishort, p); \
1724 GETLONG(cilong, p); \
1725 /* Check rejected value. */ \
1726 if (cishort != PPP_LQR || cilong != val) \
1727 goto bad; \
1728 try_.neg = 0; \
1729 }
1730 #endif /* LQR_SUPPORT */
1731 #define REJCICBCP(opt, neg, val) \
1732 if (go->neg && \
1733 len >= CILEN_CBCP && \
1734 p[1] == CILEN_CBCP && \
1735 p[0] == opt) { \
1736 len -= CILEN_CBCP; \
1737 INCPTR(2, p); \
1738 GETCHAR(cichar, p); \
1739 /* Check rejected value. */ \
1740 if (cichar != val) \
1741 goto bad; \
1742 try_.neg = 0; \
1743 }
1744 #define REJCIENDP(opt, neg, class, val, vlen) \
1745 if (go->neg && \
1746 len >= CILEN_CHAR + vlen && \
1747 p[0] == opt && \
1748 p[1] == CILEN_CHAR + vlen) { \
1749 int i; \
1750 len -= CILEN_CHAR + vlen; \
1751 INCPTR(2, p); \
1752 GETCHAR(cichar, p); \
1753 if (cichar != class) \
1754 goto bad; \
1755 for (i = 0; i < vlen; ++i) { \
1756 GETCHAR(cichar, p); \
1757 if (cichar != val[i]) \
1758 goto bad; \
1759 } \
1760 try_.neg = 0; \
1761 }
1762
1763 REJCISHORT(CI_MRU, neg_mru, go->mru);
1764 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1765 #if EAP_SUPPORT
1766 REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
1767 if (!go->neg_eap) {
1768 #endif /* EAP_SUPPORT */
1769 #if CHAP_SUPPORT
1770 REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
1771 if (!go->neg_chap) {
1772 #endif /* CHAP_SUPPORT */
1773 #if PAP_SUPPORT
1774 REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1775 #endif /* PAP_SUPPORT */
1776 #if CHAP_SUPPORT
1777 }
1778 #endif /* CHAP_SUPPORT */
1779 #if EAP_SUPPORT
1780 }
1781 #endif /* EAP_SUPPORT */
1782 #if LQR_SUPPORT
1783 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1784 #endif /* LQR_SUPPORT */
1785 REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1786 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1787 REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1788 REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1789 #ifdef HAVE_MULTILINK
1790 REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1791 #endif /* HAVE_MULTILINK */
1792 REJCIVOID(CI_SSNHF, neg_ssnhf);
1793 REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_,
1794 go->endpoint.value, go->endpoint.length);
1795
1796 /*
1797 * If there are any remaining CIs, then this packet is bad.
1798 */
1799 if (len != 0)
1800 goto bad;
1801 /*
1802 * Now we can update state.
1803 */
1804 if (f->state != PPP_FSM_OPENED)
1805 *go = try_;
1806 return 1;
1807
1808 bad:
1809 LCPDEBUG(("lcp_rejci: received bad Reject!"));
1810 return 0;
1811 }
1812
1813
1814 /*
1815 * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1816 *
1817 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1818 * appropriately. If reject_if_disagree is non-zero, doesn't return
1819 * CONFNAK; returns CONFREJ if it can't return CONFACK.
1820 *
1821 * inp = Requested CIs
1822 * lenp = Length of requested CIs
1823 */
lcp_reqci(fsm * f,u_char * inp,int * lenp,int reject_if_disagree)1824 static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) {
1825 ppp_pcb *pcb = f->pcb;
1826 lcp_options *go = &pcb->lcp_gotoptions;
1827 lcp_options *ho = &pcb->lcp_hisoptions;
1828 lcp_options *ao = &pcb->lcp_allowoptions;
1829 u_char *cip, *next; /* Pointer to current and next CIs */
1830 int cilen, citype, cichar; /* Parsed len, type, char value */
1831 u_short cishort; /* Parsed short value */
1832 u32_t cilong; /* Parse long value */
1833 int rc = CONFACK; /* Final packet return code */
1834 int orc; /* Individual option return code */
1835 u_char *p; /* Pointer to next char to parse */
1836 u_char *rejp; /* Pointer to next char in reject frame */
1837 struct pbuf *nakp; /* Nak buffer */
1838 u_char *nakoutp; /* Pointer to next char in Nak frame */
1839 int l = *lenp; /* Length left */
1840
1841 /*
1842 * Reset all his options.
1843 */
1844 BZERO(ho, sizeof(*ho));
1845
1846 /*
1847 * Process all his options.
1848 */
1849 next = inp;
1850 nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_UNKNOWN_SIZE), PBUF_RAM);
1851 if(NULL == nakp)
1852 return 0;
1853 if(nakp->tot_len != nakp->len) {
1854 pbuf_free(nakp);
1855 return 0;
1856 }
1857
1858 nakoutp = (u_char*)nakp->payload;
1859 rejp = inp;
1860 while (l) {
1861 orc = CONFACK; /* Assume success */
1862 cip = p = next; /* Remember beginning of CI */
1863 if (l < 2 || /* Not enough data for CI header or */
1864 p[1] < 2 || /* CI length too small or */
1865 p[1] > l) { /* CI length too big? */
1866 LCPDEBUG(("lcp_reqci: bad CI length!"));
1867 orc = CONFREJ; /* Reject bad CI */
1868 cilen = l; /* Reject till end of packet */
1869 l = 0; /* Don't loop again */
1870 citype = 0;
1871 goto endswitch;
1872 }
1873 GETCHAR(citype, p); /* Parse CI type */
1874 GETCHAR(cilen, p); /* Parse CI length */
1875 l -= cilen; /* Adjust remaining length */
1876 next += cilen; /* Step to next CI */
1877
1878 switch (citype) { /* Check CI type */
1879 case CI_MRU:
1880 if (!ao->neg_mru || /* Allow option? */
1881 cilen != CILEN_SHORT) { /* Check CI length */
1882 orc = CONFREJ; /* Reject CI */
1883 break;
1884 }
1885 GETSHORT(cishort, p); /* Parse MRU */
1886
1887 /*
1888 * He must be able to receive at least our minimum.
1889 * No need to check a maximum. If he sends a large number,
1890 * we'll just ignore it.
1891 */
1892 if (cishort < PPP_MINMRU) {
1893 orc = CONFNAK; /* Nak CI */
1894 PUTCHAR(CI_MRU, nakoutp);
1895 PUTCHAR(CILEN_SHORT, nakoutp);
1896 PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */
1897 break;
1898 }
1899 ho->neg_mru = 1; /* Remember he sent MRU */
1900 ho->mru = cishort; /* And remember value */
1901 break;
1902
1903 case CI_ASYNCMAP:
1904 if (!ao->neg_asyncmap ||
1905 cilen != CILEN_LONG) {
1906 orc = CONFREJ;
1907 break;
1908 }
1909 GETLONG(cilong, p);
1910
1911 /*
1912 * Asyncmap must have set at least the bits
1913 * which are set in lcp_allowoptions[unit].asyncmap.
1914 */
1915 if ((ao->asyncmap & ~cilong) != 0) {
1916 orc = CONFNAK;
1917 PUTCHAR(CI_ASYNCMAP, nakoutp);
1918 PUTCHAR(CILEN_LONG, nakoutp);
1919 PUTLONG(ao->asyncmap | cilong, nakoutp);
1920 break;
1921 }
1922 ho->neg_asyncmap = 1;
1923 ho->asyncmap = cilong;
1924 break;
1925
1926 case CI_AUTHTYPE:
1927 if (cilen < CILEN_SHORT ||
1928 !(0
1929 #if PAP_SUPPORT
1930 || ao->neg_upap
1931 #endif /* PAP_SUPPORT */
1932 #if CHAP_SUPPORT
1933 || ao->neg_chap
1934 #endif /* CHAP_SUPPORT */
1935 #if EAP_SUPPORT
1936 || ao->neg_eap
1937 #endif /* EAP_SUPPORT */
1938 )) {
1939 /*
1940 * Reject the option if we're not willing to authenticate.
1941 */
1942 ppp_dbglog(("No auth is possible"));
1943 orc = CONFREJ;
1944 break;
1945 }
1946 GETSHORT(cishort, p);
1947
1948 /*
1949 * Authtype must be PAP, CHAP, or EAP.
1950 *
1951 * Note: if more than one of ao->neg_upap, ao->neg_chap, and
1952 * ao->neg_eap are set, and the peer sends a Configure-Request
1953 * with two or more authenticate-protocol requests, then we will
1954 * reject the second request.
1955 * Whether we end up doing CHAP, UPAP, or EAP depends then on
1956 * the ordering of the CIs in the peer's Configure-Request.
1957 */
1958
1959 #if PAP_SUPPORT
1960 if (cishort == PPP_PAP) {
1961 /* we've already accepted CHAP or EAP */
1962 if (0
1963 #if CHAP_SUPPORT
1964 || ho->neg_chap
1965 #endif /* CHAP_SUPPORT */
1966 #if EAP_SUPPORT
1967 || ho->neg_eap
1968 #endif /* EAP_SUPPORT */
1969 || cilen != CILEN_SHORT) {
1970 LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1971 orc = CONFREJ;
1972 break;
1973 }
1974 if (!ao->neg_upap) { /* we don't want to do PAP */
1975 orc = CONFNAK; /* NAK it and suggest CHAP or EAP */
1976 PUTCHAR(CI_AUTHTYPE, nakoutp);
1977 #if EAP_SUPPORT
1978 if (ao->neg_eap) {
1979 PUTCHAR(CILEN_SHORT, nakoutp);
1980 PUTSHORT(PPP_EAP, nakoutp);
1981 } else {
1982 #endif /* EAP_SUPPORT */
1983 #if CHAP_SUPPORT
1984 PUTCHAR(CILEN_CHAP, nakoutp);
1985 PUTSHORT(PPP_CHAP, nakoutp);
1986 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
1987 #endif /* CHAP_SUPPORT */
1988 #if EAP_SUPPORT
1989 }
1990 #endif /* EAP_SUPPORT */
1991 break;
1992 }
1993 ho->neg_upap = 1;
1994 break;
1995 }
1996 #endif /* PAP_SUPPORT */
1997 #if CHAP_SUPPORT
1998 if (cishort == PPP_CHAP) {
1999 /* we've already accepted PAP or EAP */
2000 if (
2001 #if PAP_SUPPORT
2002 ho->neg_upap ||
2003 #endif /* PAP_SUPPORT */
2004 #if EAP_SUPPORT
2005 ho->neg_eap ||
2006 #endif /* EAP_SUPPORT */
2007 cilen != CILEN_CHAP) {
2008 LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
2009 orc = CONFREJ;
2010 break;
2011 }
2012 if (!ao->neg_chap) { /* we don't want to do CHAP */
2013 orc = CONFNAK; /* NAK it and suggest EAP or PAP */
2014 PUTCHAR(CI_AUTHTYPE, nakoutp);
2015 PUTCHAR(CILEN_SHORT, nakoutp);
2016 #if EAP_SUPPORT
2017 if (ao->neg_eap) {
2018 PUTSHORT(PPP_EAP, nakoutp);
2019 } else
2020 #endif /* EAP_SUPPORT */
2021 #if PAP_SUPPORT
2022 if(1) {
2023 PUTSHORT(PPP_PAP, nakoutp);
2024 }
2025 else
2026 #endif /* PAP_SUPPORT */
2027 {}
2028 break;
2029 }
2030 GETCHAR(cichar, p); /* get digest type */
2031 if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) {
2032 /*
2033 * We can't/won't do the requested type,
2034 * suggest something else.
2035 */
2036 orc = CONFNAK;
2037 PUTCHAR(CI_AUTHTYPE, nakoutp);
2038 PUTCHAR(CILEN_CHAP, nakoutp);
2039 PUTSHORT(PPP_CHAP, nakoutp);
2040 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2041 break;
2042 }
2043 ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */
2044 ho->neg_chap = 1;
2045 break;
2046 }
2047 #endif /* CHAP_SUPPORT */
2048 #if EAP_SUPPORT
2049 if (cishort == PPP_EAP) {
2050 /* we've already accepted CHAP or PAP */
2051 if (
2052 #if CHAP_SUPPORT
2053 ho->neg_chap ||
2054 #endif /* CHAP_SUPPORT */
2055 #if PAP_SUPPORT
2056 ho->neg_upap ||
2057 #endif /* PAP_SUPPORT */
2058 cilen != CILEN_SHORT) {
2059 LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
2060 orc = CONFREJ;
2061 break;
2062 }
2063 if (!ao->neg_eap) { /* we don't want to do EAP */
2064 orc = CONFNAK; /* NAK it and suggest CHAP or PAP */
2065 PUTCHAR(CI_AUTHTYPE, nakoutp);
2066 #if CHAP_SUPPORT
2067 if (ao->neg_chap) {
2068 PUTCHAR(CILEN_CHAP, nakoutp);
2069 PUTSHORT(PPP_CHAP, nakoutp);
2070 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2071 } else
2072 #endif /* CHAP_SUPPORT */
2073 #if PAP_SUPPORT
2074 if(1) {
2075 PUTCHAR(CILEN_SHORT, nakoutp);
2076 PUTSHORT(PPP_PAP, nakoutp);
2077 } else
2078 #endif /* PAP_SUPPORT */
2079 {}
2080 break;
2081 }
2082 ho->neg_eap = 1;
2083 break;
2084 }
2085 #endif /* EAP_SUPPORT */
2086
2087 /*
2088 * We don't recognize the protocol they're asking for.
2089 * Nak it with something we're willing to do.
2090 * (At this point we know ao->neg_upap || ao->neg_chap ||
2091 * ao->neg_eap.)
2092 */
2093 orc = CONFNAK;
2094 PUTCHAR(CI_AUTHTYPE, nakoutp);
2095
2096 #if EAP_SUPPORT
2097 if (ao->neg_eap) {
2098 PUTCHAR(CILEN_SHORT, nakoutp);
2099 PUTSHORT(PPP_EAP, nakoutp);
2100 } else
2101 #endif /* EAP_SUPPORT */
2102 #if CHAP_SUPPORT
2103 if (ao->neg_chap) {
2104 PUTCHAR(CILEN_CHAP, nakoutp);
2105 PUTSHORT(PPP_CHAP, nakoutp);
2106 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2107 } else
2108 #endif /* CHAP_SUPPORT */
2109 #if PAP_SUPPORT
2110 if(1) {
2111 PUTCHAR(CILEN_SHORT, nakoutp);
2112 PUTSHORT(PPP_PAP, nakoutp);
2113 } else
2114 #endif /* PAP_SUPPORT */
2115 {}
2116 break;
2117
2118 #if LQR_SUPPORT
2119 case CI_QUALITY:
2120 if (!ao->neg_lqr ||
2121 cilen != CILEN_LQR) {
2122 orc = CONFREJ;
2123 break;
2124 }
2125
2126 GETSHORT(cishort, p);
2127 GETLONG(cilong, p);
2128
2129 /*
2130 * Check the protocol and the reporting period.
2131 * XXX When should we Nak this, and what with?
2132 */
2133 if (cishort != PPP_LQR) {
2134 orc = CONFNAK;
2135 PUTCHAR(CI_QUALITY, nakoutp);
2136 PUTCHAR(CILEN_LQR, nakoutp);
2137 PUTSHORT(PPP_LQR, nakoutp);
2138 PUTLONG(ao->lqr_period, nakoutp);
2139 break;
2140 }
2141 break;
2142 #endif /* LQR_SUPPORT */
2143
2144 case CI_MAGICNUMBER:
2145 if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
2146 cilen != CILEN_LONG) {
2147 orc = CONFREJ;
2148 break;
2149 }
2150 GETLONG(cilong, p);
2151
2152 /*
2153 * He must have a different magic number.
2154 */
2155 if (go->neg_magicnumber &&
2156 cilong == go->magicnumber) {
2157 cilong = magic(); /* Don't put magic() inside macro! */
2158 orc = CONFNAK;
2159 PUTCHAR(CI_MAGICNUMBER, nakoutp);
2160 PUTCHAR(CILEN_LONG, nakoutp);
2161 PUTLONG(cilong, nakoutp);
2162 break;
2163 }
2164 ho->neg_magicnumber = 1;
2165 ho->magicnumber = cilong;
2166 break;
2167
2168
2169 case CI_PCOMPRESSION:
2170 if (!ao->neg_pcompression ||
2171 cilen != CILEN_VOID) {
2172 orc = CONFREJ;
2173 break;
2174 }
2175 ho->neg_pcompression = 1;
2176 break;
2177
2178 case CI_ACCOMPRESSION:
2179 if (!ao->neg_accompression ||
2180 cilen != CILEN_VOID) {
2181 orc = CONFREJ;
2182 break;
2183 }
2184 ho->neg_accompression = 1;
2185 break;
2186
2187 #ifdef HAVE_MULTILINK
2188 case CI_MRRU:
2189 if (!ao->neg_mrru
2190 || !multilink
2191 || cilen != CILEN_SHORT) {
2192 orc = CONFREJ;
2193 break;
2194 }
2195
2196 GETSHORT(cishort, p);
2197 /* possibly should insist on a minimum/maximum MRRU here */
2198 ho->neg_mrru = 1;
2199 ho->mrru = cishort;
2200 break;
2201 #endif /* HAVE_MULTILINK */
2202
2203 case CI_SSNHF:
2204 if (!ao->neg_ssnhf
2205 #ifdef HAVE_MULTILINK
2206 || !multilink
2207 #endif /* HAVE_MULTILINK */
2208 || cilen != CILEN_VOID) {
2209 orc = CONFREJ;
2210 break;
2211 }
2212 ho->neg_ssnhf = 1;
2213 break;
2214
2215 case CI_EPDISC:
2216 if (!ao->neg_endpoint ||
2217 cilen < CILEN_CHAR ||
2218 cilen > CILEN_CHAR + MAX_ENDP_LEN) {
2219 orc = CONFREJ;
2220 break;
2221 }
2222 GETCHAR(cichar, p);
2223 cilen -= CILEN_CHAR;
2224 ho->neg_endpoint = 1;
2225 ho->endpoint.class_ = cichar;
2226 ho->endpoint.length = cilen;
2227 MEMCPY(ho->endpoint.value, p, cilen);
2228 INCPTR(cilen, p);
2229 break;
2230
2231 default:
2232 LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
2233 orc = CONFREJ;
2234 break;
2235 }
2236
2237 endswitch:
2238 if (orc == CONFACK && /* Good CI */
2239 rc != CONFACK) /* but prior CI wasn't? */
2240 continue; /* Don't send this one */
2241
2242 if (orc == CONFNAK) { /* Nak this CI? */
2243 if (reject_if_disagree /* Getting fed up with sending NAKs? */
2244 && citype != CI_MAGICNUMBER) {
2245 orc = CONFREJ; /* Get tough if so */
2246 } else {
2247 if (rc == CONFREJ) /* Rejecting prior CI? */
2248 continue; /* Don't send this one */
2249 rc = CONFNAK;
2250 }
2251 }
2252 if (orc == CONFREJ) { /* Reject this CI */
2253 rc = CONFREJ;
2254 if (cip != rejp) /* Need to move rejected CI? */
2255 MEMCPY(rejp, cip, cilen); /* Move it */
2256 INCPTR(cilen, rejp); /* Update output pointer */
2257 }
2258 }
2259
2260 /*
2261 * If we wanted to send additional NAKs (for unsent CIs), the
2262 * code would go here. The extra NAKs would go at *nakoutp.
2263 * At present there are no cases where we want to ask the
2264 * peer to negotiate an option.
2265 */
2266
2267 switch (rc) {
2268 case CONFACK:
2269 *lenp = next - inp;
2270 break;
2271 case CONFNAK:
2272 /*
2273 * Copy the Nak'd options from the nak buffer to the caller's buffer.
2274 */
2275 *lenp = nakoutp - (u_char*)nakp->payload;
2276 MEMCPY(inp, nakp->payload, *lenp);
2277 break;
2278 case CONFREJ:
2279 *lenp = rejp - inp;
2280 break;
2281 default:
2282 break;
2283 }
2284
2285 pbuf_free(nakp);
2286 LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
2287 return (rc); /* Return final code */
2288 }
2289
2290
2291 /*
2292 * lcp_up - LCP has come UP.
2293 */
lcp_up(fsm * f)2294 static void lcp_up(fsm *f) {
2295 ppp_pcb *pcb = f->pcb;
2296 lcp_options *wo = &pcb->lcp_wantoptions;
2297 lcp_options *ho = &pcb->lcp_hisoptions;
2298 lcp_options *go = &pcb->lcp_gotoptions;
2299 lcp_options *ao = &pcb->lcp_allowoptions;
2300 int mtu, mru;
2301
2302 if (!go->neg_magicnumber)
2303 go->magicnumber = 0;
2304 if (!ho->neg_magicnumber)
2305 ho->magicnumber = 0;
2306
2307 /*
2308 * Set our MTU to the smaller of the MTU we wanted and
2309 * the MRU our peer wanted. If we negotiated an MRU,
2310 * set our MRU to the larger of value we wanted and
2311 * the value we got in the negotiation.
2312 * Note on the MTU: the link MTU can be the MRU the peer wanted,
2313 * the interface MTU is set to the lowest of that, the
2314 * MTU we want to use, and our link MRU.
2315 */
2316 mtu = ho->neg_mru? ho->mru: PPP_DEFMRU;
2317 mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_DEFMRU;
2318 #ifdef HAVE_MULTILINK
2319 if (!(multilink && go->neg_mrru && ho->neg_mrru))
2320 #endif /* HAVE_MULTILINK */
2321 ppp_netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru));
2322 ppp_send_config(pcb, mtu,
2323 (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
2324 ho->neg_pcompression, ho->neg_accompression);
2325 ppp_recv_config(pcb, mru,
2326 (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
2327 go->neg_pcompression, go->neg_accompression);
2328
2329 if (ho->neg_mru)
2330 pcb->peer_mru = ho->mru;
2331
2332 lcp_echo_lowerup(f->pcb); /* Enable echo messages */
2333
2334 link_established(pcb);
2335 }
2336
2337
2338 /*
2339 * lcp_down - LCP has gone DOWN.
2340 *
2341 * Alert other protocols.
2342 */
lcp_down(fsm * f)2343 static void lcp_down(fsm *f) {
2344 ppp_pcb *pcb = f->pcb;
2345 lcp_options *go = &pcb->lcp_gotoptions;
2346
2347 lcp_echo_lowerdown(f->pcb);
2348
2349 link_down(pcb);
2350
2351 ppp_send_config(pcb, PPP_DEFMRU, 0xffffffff, 0, 0);
2352 ppp_recv_config(pcb, PPP_DEFMRU,
2353 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
2354 go->neg_pcompression, go->neg_accompression);
2355 pcb->peer_mru = PPP_DEFMRU;
2356 }
2357
2358
2359 /*
2360 * lcp_starting - LCP needs the lower layer up.
2361 */
lcp_starting(fsm * f)2362 static void lcp_starting(fsm *f) {
2363 ppp_pcb *pcb = f->pcb;
2364 link_required(pcb);
2365 }
2366
2367
2368 /*
2369 * lcp_finished - LCP has finished with the lower layer.
2370 */
lcp_finished(fsm * f)2371 static void lcp_finished(fsm *f) {
2372 ppp_pcb *pcb = f->pcb;
2373 link_terminated(pcb);
2374 }
2375
2376
2377 #if PRINTPKT_SUPPORT
2378 /*
2379 * lcp_printpkt - print the contents of an LCP packet.
2380 */
2381 static const char* const lcp_codenames[] = {
2382 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
2383 "TermReq", "TermAck", "CodeRej", "ProtRej",
2384 "EchoReq", "EchoRep", "DiscReq", "Ident",
2385 "TimeRem"
2386 };
2387
lcp_printpkt(const u_char * p,int plen,void (* printer)(void *,const char *,...),void * arg)2388 static int lcp_printpkt(const u_char *p, int plen,
2389 void (*printer) (void *, const char *, ...), void *arg) {
2390 int code, id, len, olen, i;
2391 const u_char *pstart, *optend;
2392 u_short cishort;
2393 u32_t cilong;
2394
2395 if (plen < HEADERLEN)
2396 return 0;
2397 pstart = p;
2398 GETCHAR(code, p);
2399 GETCHAR(id, p);
2400 GETSHORT(len, p);
2401 if (len < HEADERLEN || len > plen)
2402 return 0;
2403
2404 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames))
2405 printer(arg, " %s", lcp_codenames[code-1]);
2406 else
2407 printer(arg, " code=0x%x", code);
2408 printer(arg, " id=0x%x", id);
2409 len -= HEADERLEN;
2410 switch (code) {
2411 case CONFREQ:
2412 case CONFACK:
2413 case CONFNAK:
2414 case CONFREJ:
2415 /* print option list */
2416 while (len >= 2) {
2417 GETCHAR(code, p);
2418 GETCHAR(olen, p);
2419 p -= 2;
2420 if (olen < 2 || olen > len) {
2421 break;
2422 }
2423 printer(arg, " <");
2424 len -= olen;
2425 optend = p + olen;
2426 switch (code) {
2427 case CI_MRU:
2428 if (olen == CILEN_SHORT) {
2429 p += 2;
2430 GETSHORT(cishort, p);
2431 printer(arg, "mru %d", cishort);
2432 }
2433 break;
2434 case CI_ASYNCMAP:
2435 if (olen == CILEN_LONG) {
2436 p += 2;
2437 GETLONG(cilong, p);
2438 printer(arg, "asyncmap 0x%x", cilong);
2439 }
2440 break;
2441 case CI_AUTHTYPE:
2442 if (olen >= CILEN_SHORT) {
2443 p += 2;
2444 printer(arg, "auth ");
2445 GETSHORT(cishort, p);
2446 switch (cishort) {
2447 #if PAP_SUPPORT
2448 case PPP_PAP:
2449 printer(arg, "pap");
2450 break;
2451 #endif /* PAP_SUPPORT */
2452 #if CHAP_SUPPORT
2453 case PPP_CHAP:
2454 printer(arg, "chap");
2455 if (p < optend) {
2456 switch (*p) {
2457 case CHAP_MD5:
2458 printer(arg, " MD5");
2459 ++p;
2460 break;
2461 #if MSCHAP_SUPPORT
2462 case CHAP_MICROSOFT:
2463 printer(arg, " MS");
2464 ++p;
2465 break;
2466
2467 case CHAP_MICROSOFT_V2:
2468 printer(arg, " MS-v2");
2469 ++p;
2470 break;
2471 #endif /* MSCHAP_SUPPORT */
2472 default:
2473 break;
2474 }
2475 }
2476 break;
2477 #endif /* CHAP_SUPPORT */
2478 #if EAP_SUPPORT
2479 case PPP_EAP:
2480 printer(arg, "eap");
2481 break;
2482 #endif /* EAP_SUPPORT */
2483 default:
2484 printer(arg, "0x%x", cishort);
2485 }
2486 }
2487 break;
2488 #if LQR_SUPPORT
2489 case CI_QUALITY:
2490 if (olen >= CILEN_SHORT) {
2491 p += 2;
2492 printer(arg, "quality ");
2493 GETSHORT(cishort, p);
2494 switch (cishort) {
2495 case PPP_LQR:
2496 printer(arg, "lqr");
2497 break;
2498 default:
2499 printer(arg, "0x%x", cishort);
2500 }
2501 }
2502 break;
2503 #endif /* LQR_SUPPORT */
2504 case CI_CALLBACK:
2505 if (olen >= CILEN_CHAR) {
2506 p += 2;
2507 printer(arg, "callback ");
2508 GETCHAR(cishort, p);
2509 switch (cishort) {
2510 case CBCP_OPT:
2511 printer(arg, "CBCP");
2512 break;
2513 default:
2514 printer(arg, "0x%x", cishort);
2515 }
2516 }
2517 break;
2518 case CI_MAGICNUMBER:
2519 if (olen == CILEN_LONG) {
2520 p += 2;
2521 GETLONG(cilong, p);
2522 printer(arg, "magic 0x%x", cilong);
2523 }
2524 break;
2525 case CI_PCOMPRESSION:
2526 if (olen == CILEN_VOID) {
2527 p += 2;
2528 printer(arg, "pcomp");
2529 }
2530 break;
2531 case CI_ACCOMPRESSION:
2532 if (olen == CILEN_VOID) {
2533 p += 2;
2534 printer(arg, "accomp");
2535 }
2536 break;
2537 case CI_MRRU:
2538 if (olen == CILEN_SHORT) {
2539 p += 2;
2540 GETSHORT(cishort, p);
2541 printer(arg, "mrru %d", cishort);
2542 }
2543 break;
2544 case CI_SSNHF:
2545 if (olen == CILEN_VOID) {
2546 p += 2;
2547 printer(arg, "ssnhf");
2548 }
2549 break;
2550 case CI_EPDISC:
2551 #ifdef HAVE_MULTILINK
2552 if (olen >= CILEN_CHAR) {
2553 struct epdisc epd;
2554 p += 2;
2555 GETCHAR(epd.class, p);
2556 epd.length = olen - CILEN_CHAR;
2557 if (epd.length > MAX_ENDP_LEN)
2558 epd.length = MAX_ENDP_LEN;
2559 if (epd.length > 0) {
2560 MEMCPY(epd.value, p, epd.length);
2561 p += epd.length;
2562 }
2563 printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
2564 }
2565 #else
2566 printer(arg, "endpoint");
2567 #endif
2568 break;
2569 default:
2570 break;
2571 }
2572 while (p < optend) {
2573 GETCHAR(code, p);
2574 printer(arg, " %.2x", code);
2575 }
2576 printer(arg, ">");
2577 }
2578 break;
2579
2580 case TERMACK:
2581 case TERMREQ:
2582 if (len > 0 && *p >= ' ' && *p < 0x7f) {
2583 printer(arg, " ");
2584 ppp_print_string(p, len, printer, arg);
2585 p += len;
2586 len = 0;
2587 }
2588 break;
2589
2590 case ECHOREQ:
2591 case ECHOREP:
2592 case DISCREQ:
2593 if (len >= 4) {
2594 GETLONG(cilong, p);
2595 printer(arg, " magic=0x%x", cilong);
2596 len -= 4;
2597 }
2598 break;
2599
2600 case IDENTIF:
2601 case TIMEREM:
2602 if (len >= 4) {
2603 GETLONG(cilong, p);
2604 printer(arg, " magic=0x%x", cilong);
2605 len -= 4;
2606 }
2607 if (code == TIMEREM) {
2608 if (len < 4)
2609 break;
2610 GETLONG(cilong, p);
2611 printer(arg, " seconds=%u", cilong);
2612 len -= 4;
2613 }
2614 if (len > 0) {
2615 printer(arg, " ");
2616 ppp_print_string(p, len, printer, arg);
2617 p += len;
2618 len = 0;
2619 }
2620 break;
2621 default:
2622 break;
2623 }
2624
2625 /* print the rest of the bytes in the packet */
2626 for (i = 0; i < len && i < 32; ++i) {
2627 GETCHAR(code, p);
2628 printer(arg, " %.2x", code);
2629 }
2630 if (i < len) {
2631 printer(arg, " ...");
2632 p += len - i;
2633 }
2634
2635 return p - pstart;
2636 }
2637 #endif /* PRINTPKT_SUPPORT */
2638
2639 /*
2640 * Time to shut down the link because there is nothing out there.
2641 */
2642
LcpLinkFailure(fsm * f)2643 static void LcpLinkFailure(fsm *f) {
2644 ppp_pcb *pcb = f->pcb;
2645 if (f->state == PPP_FSM_OPENED) {
2646 ppp_info(("No response to %d echo-requests", pcb->lcp_echos_pending));
2647 ppp_notice(("Serial link appears to be disconnected."));
2648 pcb->err_code = PPPERR_PEERDEAD;
2649 lcp_close(pcb, "Peer not responding");
2650 }
2651 }
2652
2653 /*
2654 * Timer expired for the LCP echo requests from this process.
2655 */
2656
LcpEchoCheck(fsm * f)2657 static void LcpEchoCheck(fsm *f) {
2658 ppp_pcb *pcb = f->pcb;
2659
2660 LcpSendEchoRequest (f);
2661 if (f->state != PPP_FSM_OPENED)
2662 return;
2663
2664 /*
2665 * Start the timer for the next interval.
2666 */
2667 if (pcb->lcp_echo_timer_running)
2668 ppp_warn(("assertion lcp_echo_timer_running==0 failed"));
2669 TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval);
2670 pcb->lcp_echo_timer_running = 1;
2671 }
2672
2673 /*
2674 * LcpEchoTimeout - Timer expired on the LCP echo
2675 */
2676
LcpEchoTimeout(void * arg)2677 static void LcpEchoTimeout(void *arg) {
2678 fsm *f = (fsm*)arg;
2679 ppp_pcb *pcb = f->pcb;
2680 if (pcb->lcp_echo_timer_running != 0) {
2681 pcb->lcp_echo_timer_running = 0;
2682 LcpEchoCheck ((fsm *) arg);
2683 }
2684 }
2685
2686 /*
2687 * LcpEchoReply - LCP has received a reply to the echo
2688 */
2689
lcp_received_echo_reply(fsm * f,int id,u_char * inp,int len)2690 static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) {
2691 ppp_pcb *pcb = f->pcb;
2692 lcp_options *go = &pcb->lcp_gotoptions;
2693 u32_t magic_val;
2694 LWIP_UNUSED_ARG(id);
2695
2696 /* Check the magic number - don't count replies from ourselves. */
2697 if (len < 4) {
2698 ppp_dbglog(("lcp: received short Echo-Reply, length %d", len));
2699 return;
2700 }
2701 GETLONG(magic_val, inp);
2702 if (go->neg_magicnumber
2703 && magic_val == go->magicnumber) {
2704 ppp_warn(("appear to have received our own echo-reply!"));
2705 return;
2706 }
2707
2708 /* Reset the number of outstanding echo frames */
2709 pcb->lcp_echos_pending = 0;
2710 }
2711
2712 /*
2713 * LcpSendEchoRequest - Send an echo request frame to the peer
2714 */
2715
LcpSendEchoRequest(fsm * f)2716 static void LcpSendEchoRequest(fsm *f) {
2717 ppp_pcb *pcb = f->pcb;
2718 lcp_options *go = &pcb->lcp_gotoptions;
2719 u32_t lcp_magic;
2720 u_char pkt[4], *pktp;
2721
2722 /*
2723 * Detect the failure of the peer at this point.
2724 */
2725 if (pcb->settings.lcp_echo_fails != 0) {
2726 if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) {
2727 LcpLinkFailure(f);
2728 pcb->lcp_echos_pending = 0;
2729 }
2730 }
2731
2732 #if PPP_LCP_ADAPTIVE
2733 /*
2734 * If adaptive echos have been enabled, only send the echo request if
2735 * no traffic was received since the last one.
2736 */
2737 if (pcb->settings.lcp_echo_adaptive) {
2738 static unsigned int last_pkts_in = 0;
2739
2740 #if PPP_STATS_SUPPORT
2741 update_link_stats(f->unit);
2742 link_stats_valid = 0;
2743 #endif /* PPP_STATS_SUPPORT */
2744
2745 if (link_stats.pkts_in != last_pkts_in) {
2746 last_pkts_in = link_stats.pkts_in;
2747 return;
2748 }
2749 }
2750 #endif
2751
2752 /*
2753 * Make and send the echo request frame.
2754 */
2755 if (f->state == PPP_FSM_OPENED) {
2756 lcp_magic = go->magicnumber;
2757 pktp = pkt;
2758 PUTLONG(lcp_magic, pktp);
2759 fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt);
2760 ++pcb->lcp_echos_pending;
2761 }
2762 }
2763
2764 /*
2765 * lcp_echo_lowerup - Start the timer for the LCP frame
2766 */
2767
lcp_echo_lowerup(ppp_pcb * pcb)2768 static void lcp_echo_lowerup(ppp_pcb *pcb) {
2769 fsm *f = &pcb->lcp_fsm;
2770
2771 /* Clear the parameters for generating echo frames */
2772 pcb->lcp_echos_pending = 0;
2773 pcb->lcp_echo_number = 0;
2774 pcb->lcp_echo_timer_running = 0;
2775
2776 /* If a timeout interval is specified then start the timer */
2777 if (pcb->settings.lcp_echo_interval != 0)
2778 LcpEchoCheck (f);
2779 }
2780
2781 /*
2782 * lcp_echo_lowerdown - Stop the timer for the LCP frame
2783 */
2784
lcp_echo_lowerdown(ppp_pcb * pcb)2785 static void lcp_echo_lowerdown(ppp_pcb *pcb) {
2786 fsm *f = &pcb->lcp_fsm;
2787
2788 if (pcb->lcp_echo_timer_running != 0) {
2789 UNTIMEOUT (LcpEchoTimeout, f);
2790 pcb->lcp_echo_timer_running = 0;
2791 }
2792 }
2793
2794 #endif /* PPP_SUPPORT */
2795