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