• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define RCSID	"$Id: lcp.c,v 1.74 2004/11/13 02:28:15 paulus Exp $"
44 
45 /*
46  * TODO:
47  */
48 
49 #include <stdio.h>
50 #include <string.h>
51 #include <stdlib.h>
52 
53 #include "pppd.h"
54 #include "fsm.h"
55 #include "lcp.h"
56 #include "chap-new.h"
57 #include "magic.h"
58 
59 static const char rcsid[] = RCSID;
60 
61 /*
62  * When the link comes up we want to be able to wait for a short while,
63  * or until seeing some input from the peer, before starting to send
64  * configure-requests.  We do this by delaying the fsm_lowerup call.
65  */
66 /* steal a bit in fsm flags word */
67 #define DELAYED_UP	0x100
68 
69 static void lcp_delayed_up __P((void *));
70 
71 /*
72  * LCP-related command-line options.
73  */
74 int	lcp_echo_interval = 0; 	/* Interval between LCP echo-requests */
75 int	lcp_echo_fails = 0;	/* Tolerance to unanswered echo-requests */
76 bool	lax_recv = 0;		/* accept control chars in asyncmap */
77 bool	noendpoint = 0;		/* don't send/accept endpoint discriminator */
78 
79 static int noopt __P((char **));
80 
81 #ifdef HAVE_MULTILINK
82 static int setendpoint __P((char **));
83 static void printendpoint __P((option_t *, void (*)(void *, char *, ...),
84 			       void *));
85 #endif /* HAVE_MULTILINK */
86 
87 static option_t lcp_option_list[] = {
88     /* LCP options */
89     { "-all", o_special_noarg, (void *)noopt,
90       "Don't request/allow any LCP options" },
91 
92     { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
93       "Disable address/control compression",
94       OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
95     { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
96       "Disable address/control compression",
97       OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
98 
99     { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
100       "Set asyncmap (for received packets)",
101       OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
102     { "-as", o_uint32, &lcp_wantoptions[0].asyncmap,
103       "Set asyncmap (for received packets)",
104       OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
105     { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
106       "Disable asyncmap negotiation",
107       OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
108       &lcp_allowoptions[0].neg_asyncmap },
109     { "-am", o_uint32, &lcp_wantoptions[0].asyncmap,
110       "Disable asyncmap negotiation",
111       OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
112       &lcp_allowoptions[0].neg_asyncmap },
113 
114     { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
115       "Disable magic number negotiation (looped-back line detection)",
116       OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
117     { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
118       "Disable magic number negotiation (looped-back line detection)",
119       OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
120 
121     { "mru", o_int, &lcp_wantoptions[0].mru,
122       "Set MRU (maximum received packet size) for negotiation",
123       OPT_PRIO, &lcp_wantoptions[0].neg_mru },
124     { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
125       "Disable MRU negotiation (use default 1500)",
126       OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
127     { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
128       "Disable MRU negotiation (use default 1500)",
129       OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
130 
131     { "mtu", o_int, &lcp_allowoptions[0].mru,
132       "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
133 
134     { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
135       "Disable protocol field compression",
136       OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
137     { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
138       "Disable protocol field compression",
139       OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
140 
141     { "passive", o_bool, &lcp_wantoptions[0].passive,
142       "Set passive mode", 1 },
143     { "-p", o_bool, &lcp_wantoptions[0].passive,
144       "Set passive mode", OPT_ALIAS | 1 },
145 
146     { "silent", o_bool, &lcp_wantoptions[0].silent,
147       "Set silent mode", 1 },
148 
149     { "lcp-echo-failure", o_int, &lcp_echo_fails,
150       "Set number of consecutive echo failures to indicate link failure",
151       OPT_PRIO },
152     { "lcp-echo-interval", o_int, &lcp_echo_interval,
153       "Set time in seconds between LCP echo requests", OPT_PRIO },
154     { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
155       "Set time in seconds between LCP retransmissions", OPT_PRIO },
156     { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
157       "Set maximum number of LCP terminate-request transmissions", OPT_PRIO },
158     { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
159       "Set maximum number of LCP configure-request transmissions", OPT_PRIO },
160     { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
161       "Set limit on number of LCP configure-naks", OPT_PRIO },
162 
163     { "receive-all", o_bool, &lax_recv,
164       "Accept all received control characters", 1 },
165 
166 #ifdef HAVE_MULTILINK
167     { "mrru", o_int, &lcp_wantoptions[0].mrru,
168       "Maximum received packet size for multilink bundle",
169       OPT_PRIO, &lcp_wantoptions[0].neg_mrru },
170 
171     { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
172       "Use short sequence numbers in multilink headers",
173       OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf },
174     { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
175       "Don't use short sequence numbers in multilink headers",
176       OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf },
177 
178     { "endpoint", o_special, (void *) setendpoint,
179       "Endpoint discriminator for multilink",
180       OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint },
181 #endif /* HAVE_MULTILINK */
182 
183     { "noendpoint", o_bool, &noendpoint,
184       "Don't send or accept multilink endpoint discriminator", 1 },
185 
186     {NULL}
187 };
188 
189 /* global vars */
190 fsm lcp_fsm[NUM_PPP];			/* LCP fsm structure (global)*/
191 lcp_options lcp_wantoptions[NUM_PPP];	/* Options that we want to request */
192 lcp_options lcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
193 lcp_options lcp_allowoptions[NUM_PPP];	/* Options we allow peer to request */
194 lcp_options lcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
195 
196 static int lcp_echos_pending = 0;	/* Number of outstanding echo msgs */
197 static int lcp_echo_number   = 0;	/* ID number of next echo frame */
198 static int lcp_echo_timer_running = 0;  /* set if a timer is running */
199 
200 static u_char nak_buffer[PPP_MRU];	/* where we construct a nak packet */
201 
202 /*
203  * Callbacks for fsm code.  (CI = Configuration Information)
204  */
205 static void lcp_resetci __P((fsm *));	/* Reset our CI */
206 static int  lcp_cilen __P((fsm *));		/* Return length of our CI */
207 static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */
208 static int  lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
209 static int  lcp_nakci __P((fsm *, u_char *, int, int)); /* Peer nak'd our CI */
210 static int  lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
211 static int  lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */
212 static void lcp_up __P((fsm *));		/* We're UP */
213 static void lcp_down __P((fsm *));		/* We're DOWN */
214 static void lcp_starting __P((fsm *));	/* We need lower layer up */
215 static void lcp_finished __P((fsm *));	/* We need lower layer down */
216 static int  lcp_extcode __P((fsm *, int, int, u_char *, int));
217 static void lcp_rprotrej __P((fsm *, u_char *, int));
218 
219 /*
220  * routines to send LCP echos to peer
221  */
222 
223 static void lcp_echo_lowerup __P((int));
224 static void lcp_echo_lowerdown __P((int));
225 static void LcpEchoTimeout __P((void *));
226 static void lcp_received_echo_reply __P((fsm *, int, u_char *, int));
227 static void LcpSendEchoRequest __P((fsm *));
228 static void LcpLinkFailure __P((fsm *));
229 static void LcpEchoCheck __P((fsm *));
230 
231 static fsm_callbacks lcp_callbacks = {	/* LCP callback routines */
232     lcp_resetci,		/* Reset our Configuration Information */
233     lcp_cilen,			/* Length of our Configuration Information */
234     lcp_addci,			/* Add our Configuration Information */
235     lcp_ackci,			/* ACK our Configuration Information */
236     lcp_nakci,			/* NAK our Configuration Information */
237     lcp_rejci,			/* Reject our Configuration Information */
238     lcp_reqci,			/* Request peer's Configuration Information */
239     lcp_up,			/* Called when fsm reaches OPENED state */
240     lcp_down,			/* Called when fsm leaves OPENED state */
241     lcp_starting,		/* Called when we want the lower layer up */
242     lcp_finished,		/* Called when we want the lower layer down */
243     NULL,			/* Called when Protocol-Reject received */
244     NULL,			/* Retransmission is necessary */
245     lcp_extcode,		/* Called to handle LCP-specific codes */
246     "LCP"			/* String name of protocol */
247 };
248 
249 /*
250  * Protocol entry points.
251  * Some of these are called directly.
252  */
253 
254 static void lcp_init __P((int));
255 static void lcp_input __P((int, u_char *, int));
256 static void lcp_protrej __P((int));
257 static int  lcp_printpkt __P((u_char *, int,
258 			      void (*) __P((void *, char *, ...)), void *));
259 
260 struct protent lcp_protent = {
261     PPP_LCP,
262     lcp_init,
263     lcp_input,
264     lcp_protrej,
265     lcp_lowerup,
266     lcp_lowerdown,
267     lcp_open,
268     lcp_close,
269     lcp_printpkt,
270     NULL,
271     1,
272     "LCP",
273     NULL,
274     lcp_option_list,
275     NULL,
276     NULL,
277     NULL
278 };
279 
280 int lcp_loopbackfail = DEFLOOPBACKFAIL;
281 
282 /*
283  * Length of each type of configuration option (in octets)
284  */
285 #define CILEN_VOID	2
286 #define CILEN_CHAR	3
287 #define CILEN_SHORT	4	/* CILEN_VOID + 2 */
288 #define CILEN_CHAP	5	/* CILEN_VOID + 2 + 1 */
289 #define CILEN_LONG	6	/* CILEN_VOID + 4 */
290 #define CILEN_LQR	8	/* CILEN_VOID + 2 + 4 */
291 #define CILEN_CBCP	3
292 
293 #define CODENAME(x)	((x) == CONFACK ? "ACK" : \
294 			 (x) == CONFNAK ? "NAK" : "REJ")
295 
296 /*
297  * noopt - Disable all options (why?).
298  */
299 static int
noopt(argv)300 noopt(argv)
301     char **argv;
302 {
303     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
304     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
305 
306     return (1);
307 }
308 
309 #ifdef HAVE_MULTILINK
310 static int
setendpoint(argv)311 setendpoint(argv)
312     char **argv;
313 {
314     if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
315 	lcp_wantoptions[0].neg_endpoint = 1;
316 	return 1;
317     }
318     option_error("Can't parse '%s' as an endpoint discriminator", *argv);
319     return 0;
320 }
321 
322 static void
printendpoint(opt,printer,arg)323 printendpoint(opt, printer, arg)
324     option_t *opt;
325     void (*printer) __P((void *, char *, ...));
326     void *arg;
327 {
328 	printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));
329 }
330 #endif /* HAVE_MULTILINK */
331 
332 /*
333  * lcp_init - Initialize LCP.
334  */
335 static void
lcp_init(unit)336 lcp_init(unit)
337     int unit;
338 {
339     fsm *f = &lcp_fsm[unit];
340     lcp_options *wo = &lcp_wantoptions[unit];
341     lcp_options *ao = &lcp_allowoptions[unit];
342 
343     f->unit = unit;
344     f->protocol = PPP_LCP;
345     f->callbacks = &lcp_callbacks;
346 
347     fsm_init(f);
348 
349     BZERO(wo, sizeof(*wo));
350     wo->neg_mru = 1;
351     wo->mru = DEFMRU;
352     wo->neg_asyncmap = 1;
353     wo->neg_magicnumber = 1;
354     wo->neg_pcompression = 1;
355     wo->neg_accompression = 1;
356 
357     BZERO(ao, sizeof(*ao));
358     ao->neg_mru = 1;
359     ao->mru = MAXMRU;
360     ao->neg_asyncmap = 1;
361     ao->neg_chap = 1;
362     ao->chap_mdtype = chap_mdtype_all;
363     ao->neg_upap = 1;
364     ao->neg_eap = 1;
365     ao->neg_magicnumber = 1;
366     ao->neg_pcompression = 1;
367     ao->neg_accompression = 1;
368     ao->neg_endpoint = 1;
369 }
370 
371 
372 /*
373  * lcp_open - LCP is allowed to come up.
374  */
375 void
lcp_open(unit)376 lcp_open(unit)
377     int unit;
378 {
379     fsm *f = &lcp_fsm[unit];
380     lcp_options *wo = &lcp_wantoptions[unit];
381 
382     f->flags &= ~(OPT_PASSIVE | OPT_SILENT);
383     if (wo->passive)
384 	f->flags |= OPT_PASSIVE;
385     if (wo->silent)
386 	f->flags |= OPT_SILENT;
387     fsm_open(f);
388 }
389 
390 
391 /*
392  * lcp_close - Take LCP down.
393  */
394 void
lcp_close(unit,reason)395 lcp_close(unit, reason)
396     int unit;
397     char *reason;
398 {
399     fsm *f = &lcp_fsm[unit];
400 
401     if (phase != PHASE_DEAD && phase != PHASE_MASTER)
402 	new_phase(PHASE_TERMINATE);
403     if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
404 	/*
405 	 * This action is not strictly according to the FSM in RFC1548,
406 	 * but it does mean that the program terminates if you do a
407 	 * lcp_close() in passive/silent mode when a connection hasn't
408 	 * been established.
409 	 */
410 	f->state = CLOSED;
411 	lcp_finished(f);
412 
413     } else
414 	fsm_close(f, reason);
415 }
416 
417 
418 /*
419  * lcp_lowerup - The lower layer is up.
420  */
421 void
lcp_lowerup(unit)422 lcp_lowerup(unit)
423     int unit;
424 {
425     lcp_options *wo = &lcp_wantoptions[unit];
426     fsm *f = &lcp_fsm[unit];
427 
428     /*
429      * Don't use A/C or protocol compression on transmission,
430      * but accept A/C and protocol compressed packets
431      * if we are going to ask for A/C and protocol compression.
432      */
433     if (ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0) < 0
434 	|| ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff),
435 			   wo->neg_pcompression, wo->neg_accompression) < 0)
436 	    return;
437     peer_mru[unit] = PPP_MRU;
438 
439     if (listen_time != 0) {
440 	f->flags |= DELAYED_UP;
441 	timeout(lcp_delayed_up, f, 0, listen_time * 1000);
442     } else
443 	fsm_lowerup(f);
444 }
445 
446 
447 /*
448  * lcp_lowerdown - The lower layer is down.
449  */
450 void
lcp_lowerdown(unit)451 lcp_lowerdown(unit)
452     int unit;
453 {
454     fsm *f = &lcp_fsm[unit];
455 
456     if (f->flags & DELAYED_UP)
457 	f->flags &= ~DELAYED_UP;
458     else
459 	fsm_lowerdown(&lcp_fsm[unit]);
460 }
461 
462 
463 /*
464  * lcp_delayed_up - Bring the lower layer up now.
465  */
466 static void
lcp_delayed_up(arg)467 lcp_delayed_up(arg)
468     void *arg;
469 {
470     fsm *f = arg;
471 
472     if (f->flags & DELAYED_UP) {
473 	f->flags &= ~DELAYED_UP;
474 	fsm_lowerup(f);
475     }
476 }
477 
478 
479 /*
480  * lcp_input - Input LCP packet.
481  */
482 static void
lcp_input(unit,p,len)483 lcp_input(unit, p, len)
484     int unit;
485     u_char *p;
486     int len;
487 {
488     fsm *f = &lcp_fsm[unit];
489 
490     if (f->flags & DELAYED_UP) {
491 	f->flags &= ~DELAYED_UP;
492 	fsm_lowerup(f);
493     }
494     fsm_input(f, p, len);
495 }
496 
497 
498 /*
499  * lcp_extcode - Handle a LCP-specific code.
500  */
501 static int
lcp_extcode(f,code,id,inp,len)502 lcp_extcode(f, code, id, inp, len)
503     fsm *f;
504     int code, id;
505     u_char *inp;
506     int len;
507 {
508     u_char *magp;
509 
510     switch( code ){
511     case PROTREJ:
512 	lcp_rprotrej(f, inp, len);
513 	break;
514 
515     case ECHOREQ:
516 	if (f->state != OPENED)
517 	    break;
518 	magp = inp;
519 	PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
520 	fsm_sdata(f, ECHOREP, id, inp, len);
521 	break;
522 
523     case ECHOREP:
524 	lcp_received_echo_reply(f, id, inp, len);
525 	break;
526 
527     case DISCREQ:
528 	break;
529 
530     default:
531 	return 0;
532     }
533     return 1;
534 }
535 
536 
537 /*
538  * lcp_rprotrej - Receive an Protocol-Reject.
539  *
540  * Figure out which protocol is rejected and inform it.
541  */
542 static void
lcp_rprotrej(f,inp,len)543 lcp_rprotrej(f, inp, len)
544     fsm *f;
545     u_char *inp;
546     int len;
547 {
548     int i;
549     struct protent *protp;
550     u_short prot;
551 
552     if (len < 2) {
553 	LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
554 	return;
555     }
556 
557     GETSHORT(prot, inp);
558 
559     /*
560      * Protocol-Reject packets received in any state other than the LCP
561      * OPENED state SHOULD be silently discarded.
562      */
563     if( f->state != OPENED ){
564 	LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state));
565 	return;
566     }
567 
568     /*
569      * Upcall the proper Protocol-Reject routine.
570      */
571     for (i = 0; (protp = protocols[i]) != NULL; ++i)
572 	if (protp->protocol == prot && protp->enabled_flag) {
573 	    (*protp->protrej)(f->unit);
574 	    return;
575 	}
576 
577     warn("Protocol-Reject for unsupported protocol 0x%x", prot);
578 }
579 
580 
581 /*
582  * lcp_protrej - A Protocol-Reject was received.
583  */
584 /*ARGSUSED*/
585 static void
lcp_protrej(unit)586 lcp_protrej(unit)
587     int unit;
588 {
589     /*
590      * Can't reject LCP!
591      */
592     error("Received Protocol-Reject for LCP!");
593     fsm_protreject(&lcp_fsm[unit]);
594 }
595 
596 
597 /*
598  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
599  */
600 void
lcp_sprotrej(unit,p,len)601 lcp_sprotrej(unit, p, len)
602     int unit;
603     u_char *p;
604     int len;
605 {
606     /*
607      * Send back the protocol and the information field of the
608      * rejected packet.  We only get here if LCP is in the OPENED state.
609      */
610     p += 2;
611     len -= 2;
612 
613     fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
614 	      p, len);
615 }
616 
617 
618 /*
619  * lcp_resetci - Reset our CI.
620  */
621 static void
lcp_resetci(f)622 lcp_resetci(f)
623     fsm *f;
624 {
625     lcp_options *wo = &lcp_wantoptions[f->unit];
626     lcp_options *go = &lcp_gotoptions[f->unit];
627     lcp_options *ao = &lcp_allowoptions[f->unit];
628 
629     wo->magicnumber = magic();
630     wo->numloops = 0;
631     *go = *wo;
632     if (!multilink) {
633 	go->neg_mrru = 0;
634 	go->neg_ssnhf = 0;
635 	go->neg_endpoint = 0;
636     }
637     if (noendpoint)
638 	ao->neg_endpoint = 0;
639     peer_mru[f->unit] = PPP_MRU;
640     auth_reset(f->unit);
641 }
642 
643 
644 /*
645  * lcp_cilen - Return length of our CI.
646  */
647 static int
lcp_cilen(f)648 lcp_cilen(f)
649     fsm *f;
650 {
651     lcp_options *go = &lcp_gotoptions[f->unit];
652 
653 #define LENCIVOID(neg)	((neg) ? CILEN_VOID : 0)
654 #define LENCICHAP(neg)	((neg) ? CILEN_CHAP : 0)
655 #define LENCISHORT(neg)	((neg) ? CILEN_SHORT : 0)
656 #define LENCILONG(neg)	((neg) ? CILEN_LONG : 0)
657 #define LENCILQR(neg)	((neg) ? CILEN_LQR: 0)
658 #define LENCICBCP(neg)	((neg) ? CILEN_CBCP: 0)
659     /*
660      * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will
661      * accept more than one.  We prefer EAP first, then CHAP, then
662      * PAP.
663      */
664     return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
665 	    LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
666 	    LENCISHORT(go->neg_eap) +
667 	    LENCICHAP(!go->neg_eap && go->neg_chap) +
668 	    LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) +
669 	    LENCILQR(go->neg_lqr) +
670 	    LENCICBCP(go->neg_cbcp) +
671 	    LENCILONG(go->neg_magicnumber) +
672 	    LENCIVOID(go->neg_pcompression) +
673 	    LENCIVOID(go->neg_accompression) +
674 	    LENCISHORT(go->neg_mrru) +
675 	    LENCIVOID(go->neg_ssnhf) +
676 	    (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
677 }
678 
679 
680 /*
681  * lcp_addci - Add our desired CIs to a packet.
682  */
683 static void
lcp_addci(f,ucp,lenp)684 lcp_addci(f, ucp, lenp)
685     fsm *f;
686     u_char *ucp;
687     int *lenp;
688 {
689     lcp_options *go = &lcp_gotoptions[f->unit];
690     u_char *start_ucp = ucp;
691 
692 #define ADDCIVOID(opt, neg) \
693     if (neg) { \
694 	PUTCHAR(opt, ucp); \
695 	PUTCHAR(CILEN_VOID, ucp); \
696     }
697 #define ADDCISHORT(opt, neg, val) \
698     if (neg) { \
699 	PUTCHAR(opt, ucp); \
700 	PUTCHAR(CILEN_SHORT, ucp); \
701 	PUTSHORT(val, ucp); \
702     }
703 #define ADDCICHAP(opt, neg, val) \
704     if (neg) { \
705 	PUTCHAR((opt), ucp); \
706 	PUTCHAR(CILEN_CHAP, ucp); \
707 	PUTSHORT(PPP_CHAP, ucp); \
708 	PUTCHAR((CHAP_DIGEST(val)), ucp); \
709     }
710 #define ADDCILONG(opt, neg, val) \
711     if (neg) { \
712 	PUTCHAR(opt, ucp); \
713 	PUTCHAR(CILEN_LONG, ucp); \
714 	PUTLONG(val, ucp); \
715     }
716 #define ADDCILQR(opt, neg, val) \
717     if (neg) { \
718 	PUTCHAR(opt, ucp); \
719 	PUTCHAR(CILEN_LQR, ucp); \
720 	PUTSHORT(PPP_LQR, ucp); \
721 	PUTLONG(val, ucp); \
722     }
723 #define ADDCICHAR(opt, neg, val) \
724     if (neg) { \
725 	PUTCHAR(opt, ucp); \
726 	PUTCHAR(CILEN_CHAR, ucp); \
727 	PUTCHAR(val, ucp); \
728     }
729 #define ADDCIENDP(opt, neg, class, val, len) \
730     if (neg) { \
731 	int i; \
732 	PUTCHAR(opt, ucp); \
733 	PUTCHAR(CILEN_CHAR + len, ucp); \
734 	PUTCHAR(class, ucp); \
735 	for (i = 0; i < len; ++i) \
736 	    PUTCHAR(val[i], ucp); \
737     }
738 
739     ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
740     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
741 	      go->asyncmap);
742     ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
743     ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
744     ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap,
745 	       PPP_PAP);
746     ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
747     ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
748     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
749     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
750     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
751     ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
752     ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
753     ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
754 	      go->endpoint.value, go->endpoint.length);
755 
756     if (ucp - start_ucp != *lenp) {
757 	/* this should never happen, because peer_mtu should be 1500 */
758 	error("Bug in lcp_addci: wrong length");
759     }
760 }
761 
762 
763 /*
764  * lcp_ackci - Ack our CIs.
765  * This should not modify any state if the Ack is bad.
766  *
767  * Returns:
768  *	0 - Ack was bad.
769  *	1 - Ack was good.
770  */
771 static int
lcp_ackci(f,p,len)772 lcp_ackci(f, p, len)
773     fsm *f;
774     u_char *p;
775     int len;
776 {
777     lcp_options *go = &lcp_gotoptions[f->unit];
778     u_char cilen, citype, cichar;
779     u_short cishort;
780     u_int32_t cilong;
781 
782     /*
783      * CIs must be in exactly the same order that we sent.
784      * Check packet length and CI length at each step.
785      * If we find any deviations, then this packet is bad.
786      */
787 #define ACKCIVOID(opt, neg) \
788     if (neg) { \
789 	if ((len -= CILEN_VOID) < 0) \
790 	    goto bad; \
791 	GETCHAR(citype, p); \
792 	GETCHAR(cilen, p); \
793 	if (cilen != CILEN_VOID || \
794 	    citype != opt) \
795 	    goto bad; \
796     }
797 #define ACKCISHORT(opt, neg, val) \
798     if (neg) { \
799 	if ((len -= CILEN_SHORT) < 0) \
800 	    goto bad; \
801 	GETCHAR(citype, p); \
802 	GETCHAR(cilen, p); \
803 	if (cilen != CILEN_SHORT || \
804 	    citype != opt) \
805 	    goto bad; \
806 	GETSHORT(cishort, p); \
807 	if (cishort != val) \
808 	    goto bad; \
809     }
810 #define ACKCICHAR(opt, neg, val) \
811     if (neg) { \
812 	if ((len -= CILEN_CHAR) < 0) \
813 	    goto bad; \
814 	GETCHAR(citype, p); \
815 	GETCHAR(cilen, p); \
816 	if (cilen != CILEN_CHAR || \
817 	    citype != opt) \
818 	    goto bad; \
819 	GETCHAR(cichar, p); \
820 	if (cichar != val) \
821 	    goto bad; \
822     }
823 #define ACKCICHAP(opt, neg, val) \
824     if (neg) { \
825 	if ((len -= CILEN_CHAP) < 0) \
826 	    goto bad; \
827 	GETCHAR(citype, p); \
828 	GETCHAR(cilen, p); \
829 	if (cilen != CILEN_CHAP || \
830 	    citype != (opt)) \
831 	    goto bad; \
832 	GETSHORT(cishort, p); \
833 	if (cishort != PPP_CHAP) \
834 	    goto bad; \
835 	GETCHAR(cichar, p); \
836 	if (cichar != (CHAP_DIGEST(val))) \
837 	  goto bad; \
838     }
839 #define ACKCILONG(opt, neg, val) \
840     if (neg) { \
841 	if ((len -= CILEN_LONG) < 0) \
842 	    goto bad; \
843 	GETCHAR(citype, p); \
844 	GETCHAR(cilen, p); \
845 	if (cilen != CILEN_LONG || \
846 	    citype != opt) \
847 	    goto bad; \
848 	GETLONG(cilong, p); \
849 	if (cilong != val) \
850 	    goto bad; \
851     }
852 #define ACKCILQR(opt, neg, val) \
853     if (neg) { \
854 	if ((len -= CILEN_LQR) < 0) \
855 	    goto bad; \
856 	GETCHAR(citype, p); \
857 	GETCHAR(cilen, p); \
858 	if (cilen != CILEN_LQR || \
859 	    citype != opt) \
860 	    goto bad; \
861 	GETSHORT(cishort, p); \
862 	if (cishort != PPP_LQR) \
863 	    goto bad; \
864 	GETLONG(cilong, p); \
865 	if (cilong != val) \
866 	  goto bad; \
867     }
868 #define ACKCIENDP(opt, neg, class, val, vlen) \
869     if (neg) { \
870 	int i; \
871 	if ((len -= CILEN_CHAR + vlen) < 0) \
872 	    goto bad; \
873 	GETCHAR(citype, p); \
874 	GETCHAR(cilen, p); \
875 	if (cilen != CILEN_CHAR + vlen || \
876 	    citype != opt) \
877 	    goto bad; \
878 	GETCHAR(cichar, p); \
879 	if (cichar != class) \
880 	    goto bad; \
881 	for (i = 0; i < vlen; ++i) { \
882 	    GETCHAR(cichar, p); \
883 	    if (cichar != val[i]) \
884 		goto bad; \
885 	} \
886     }
887 
888     ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
889     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
890 	      go->asyncmap);
891     ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
892     ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
893     ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap,
894 	       PPP_PAP);
895     ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
896     ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
897     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
898     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
899     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
900     ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
901     ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
902     ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
903 	      go->endpoint.value, go->endpoint.length);
904 
905     /*
906      * If there are any remaining CIs, then this packet is bad.
907      */
908     if (len != 0)
909 	goto bad;
910     return (1);
911 bad:
912     LCPDEBUG(("lcp_acki: received bad Ack!"));
913     return (0);
914 }
915 
916 
917 /*
918  * lcp_nakci - Peer has sent a NAK for some of our CIs.
919  * This should not modify any state if the Nak is bad
920  * or if LCP is in the OPENED state.
921  *
922  * Returns:
923  *	0 - Nak was bad.
924  *	1 - Nak was good.
925  */
926 static int
lcp_nakci(f,p,len,treat_as_reject)927 lcp_nakci(f, p, len, treat_as_reject)
928     fsm *f;
929     u_char *p;
930     int len;
931     int treat_as_reject;
932 {
933     lcp_options *go = &lcp_gotoptions[f->unit];
934     lcp_options *wo = &lcp_wantoptions[f->unit];
935     u_char citype, cichar, *next;
936     u_short cishort;
937     u_int32_t cilong;
938     lcp_options no;		/* options we've seen Naks for */
939     lcp_options try;		/* options to request next time */
940     int looped_back = 0;
941     int cilen;
942 
943     BZERO(&no, sizeof(no));
944     try = *go;
945 
946     /*
947      * Any Nak'd CIs must be in exactly the same order that we sent.
948      * Check packet length and CI length at each step.
949      * If we find any deviations, then this packet is bad.
950      */
951 #define NAKCIVOID(opt, neg) \
952     if (go->neg && \
953 	len >= CILEN_VOID && \
954 	p[1] == CILEN_VOID && \
955 	p[0] == opt) { \
956 	len -= CILEN_VOID; \
957 	INCPTR(CILEN_VOID, p); \
958 	no.neg = 1; \
959 	try.neg = 0; \
960     }
961 #define NAKCICHAP(opt, neg, code) \
962     if (go->neg && \
963 	len >= CILEN_CHAP && \
964 	p[1] == CILEN_CHAP && \
965 	p[0] == opt) { \
966 	len -= CILEN_CHAP; \
967 	INCPTR(2, p); \
968 	GETSHORT(cishort, p); \
969 	GETCHAR(cichar, p); \
970 	no.neg = 1; \
971 	code \
972     }
973 #define NAKCICHAR(opt, neg, code) \
974     if (go->neg && \
975 	len >= CILEN_CHAR && \
976 	p[1] == CILEN_CHAR && \
977 	p[0] == opt) { \
978 	len -= CILEN_CHAR; \
979 	INCPTR(2, p); \
980 	GETCHAR(cichar, p); \
981 	no.neg = 1; \
982 	code \
983     }
984 #define NAKCISHORT(opt, neg, code) \
985     if (go->neg && \
986 	len >= CILEN_SHORT && \
987 	p[1] == CILEN_SHORT && \
988 	p[0] == opt) { \
989 	len -= CILEN_SHORT; \
990 	INCPTR(2, p); \
991 	GETSHORT(cishort, p); \
992 	no.neg = 1; \
993 	code \
994     }
995 #define NAKCILONG(opt, neg, code) \
996     if (go->neg && \
997 	len >= CILEN_LONG && \
998 	p[1] == CILEN_LONG && \
999 	p[0] == opt) { \
1000 	len -= CILEN_LONG; \
1001 	INCPTR(2, p); \
1002 	GETLONG(cilong, p); \
1003 	no.neg = 1; \
1004 	code \
1005     }
1006 #define NAKCILQR(opt, neg, code) \
1007     if (go->neg && \
1008 	len >= CILEN_LQR && \
1009 	p[1] == CILEN_LQR && \
1010 	p[0] == opt) { \
1011 	len -= CILEN_LQR; \
1012 	INCPTR(2, p); \
1013 	GETSHORT(cishort, p); \
1014 	GETLONG(cilong, p); \
1015 	no.neg = 1; \
1016 	code \
1017     }
1018 #define NAKCIENDP(opt, neg) \
1019     if (go->neg && \
1020 	len >= CILEN_CHAR && \
1021 	p[0] == opt && \
1022 	p[1] >= CILEN_CHAR && \
1023 	p[1] <= len) { \
1024 	len -= p[1]; \
1025 	INCPTR(p[1], p); \
1026 	no.neg = 1; \
1027 	try.neg = 0; \
1028     }
1029 
1030     /*
1031      * NOTE!  There must be no assignments to individual fields of *go in
1032      * the code below.  Any such assignment is a BUG!
1033      */
1034     /*
1035      * We don't care if they want to send us smaller packets than
1036      * we want.  Therefore, accept any MRU less than what we asked for,
1037      * but then ignore the new value when setting the MRU in the kernel.
1038      * If they send us a bigger MRU than what we asked, accept it, up to
1039      * the limit of the default MRU we'd get if we didn't negotiate.
1040      */
1041     if (go->neg_mru && go->mru != DEFMRU) {
1042 	NAKCISHORT(CI_MRU, neg_mru,
1043 		   if (cishort <= wo->mru || cishort <= DEFMRU)
1044 		       try.mru = cishort;
1045 		   );
1046     }
1047 
1048     /*
1049      * Add any characters they want to our (receive-side) asyncmap.
1050      */
1051     if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
1052 	NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
1053 		  try.asyncmap = go->asyncmap | cilong;
1054 		  );
1055     }
1056 
1057     /*
1058      * If they've nak'd our authentication-protocol, check whether
1059      * they are proposing a different protocol, or a different
1060      * hash algorithm for CHAP.
1061      */
1062     if ((go->neg_chap || go->neg_upap || go->neg_eap)
1063 	&& len >= CILEN_SHORT
1064 	&& p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
1065 	cilen = p[1];
1066 	len -= cilen;
1067 	no.neg_chap = go->neg_chap;
1068 	no.neg_upap = go->neg_upap;
1069 	no.neg_eap = go->neg_eap;
1070 	INCPTR(2, p);
1071 	GETSHORT(cishort, p);
1072 	if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
1073 	    /* If we were asking for EAP, then we need to stop that. */
1074 	    if (go->neg_eap)
1075 		try.neg_eap = 0;
1076 
1077 	    /* If we were asking for CHAP, then we need to stop that. */
1078 	    else if (go->neg_chap)
1079 		try.neg_chap = 0;
1080 	    /*
1081 	     * If we weren't asking for CHAP or EAP, then we were asking for
1082 	     * PAP, in which case this Nak is bad.
1083 	     */
1084 	    else
1085 		goto bad;
1086 
1087 	} else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
1088 	    GETCHAR(cichar, p);
1089 	    /* Stop asking for EAP, if we were. */
1090 	    if (go->neg_eap) {
1091 		try.neg_eap = 0;
1092 		/* Try to set up to use their suggestion, if possible */
1093 		if (CHAP_CANDIGEST(go->chap_mdtype, cichar))
1094 		    try.chap_mdtype = CHAP_MDTYPE_D(cichar);
1095 	    } else if (go->neg_chap) {
1096 		/*
1097 		 * We were asking for our preferred algorithm, they must
1098 		 * want something different.
1099 		 */
1100 		if (cichar != CHAP_DIGEST(go->chap_mdtype)) {
1101 		    if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) {
1102 			/* Use their suggestion if we support it ... */
1103 			try.chap_mdtype = CHAP_MDTYPE_D(cichar);
1104 		    } else {
1105 			/* ... otherwise, try our next-preferred algorithm. */
1106 			try.chap_mdtype &= ~(CHAP_MDTYPE(try.chap_mdtype));
1107 			if (try.chap_mdtype == MDTYPE_NONE) /* out of algos */
1108 			    try.neg_chap = 0;
1109 		    }
1110 		} else {
1111 		    /*
1112 		     * Whoops, they Nak'd our algorithm of choice
1113 		     * but then suggested it back to us.
1114 		     */
1115 		    goto bad;
1116 		}
1117 	    } else {
1118 		/*
1119 		 * Stop asking for PAP if we were asking for it.
1120 		 */
1121 		try.neg_upap = 0;
1122 	    }
1123 
1124 	} else {
1125 
1126 	    /*
1127 	     * If we were asking for EAP, and they're Conf-Naking EAP,
1128 	     * well, that's just strange.  Nobody should do that.
1129 	     */
1130 	    if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap)
1131 		dbglog("Unexpected Conf-Nak for EAP");
1132 
1133 	    /*
1134 	     * We don't recognize what they're suggesting.
1135 	     * Stop asking for what we were asking for.
1136 	     */
1137 	    if (go->neg_eap)
1138 		try.neg_eap = 0;
1139 	    else if (go->neg_chap)
1140 		try.neg_chap = 0;
1141 	    else
1142 		try.neg_upap = 0;
1143 	    p += cilen - CILEN_SHORT;
1144 	}
1145     }
1146 
1147     /*
1148      * If they can't cope with our link quality protocol, we'll have
1149      * to stop asking for LQR.  We haven't got any other protocol.
1150      * If they Nak the reporting period, take their value XXX ?
1151      */
1152     NAKCILQR(CI_QUALITY, neg_lqr,
1153 	     if (cishort != PPP_LQR)
1154 		 try.neg_lqr = 0;
1155 	     else
1156 		 try.lqr_period = cilong;
1157 	     );
1158 
1159     /*
1160      * Only implementing CBCP...not the rest of the callback options
1161      */
1162     NAKCICHAR(CI_CALLBACK, neg_cbcp,
1163               try.neg_cbcp = 0;
1164               );
1165 
1166     /*
1167      * Check for a looped-back line.
1168      */
1169     NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1170 	      try.magicnumber = magic();
1171 	      looped_back = 1;
1172 	      );
1173 
1174     /*
1175      * Peer shouldn't send Nak for protocol compression or
1176      * address/control compression requests; they should send
1177      * a Reject instead.  If they send a Nak, treat it as a Reject.
1178      */
1179     NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1180     NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1181 
1182     /*
1183      * Nak for MRRU option - accept their value if it is smaller
1184      * than the one we want.
1185      */
1186     if (go->neg_mrru) {
1187 	NAKCISHORT(CI_MRRU, neg_mrru,
1188 		   if (treat_as_reject)
1189 		       try.neg_mrru = 0;
1190 		   else if (cishort <= wo->mrru)
1191 		       try.mrru = cishort;
1192 		   );
1193     }
1194 
1195     /*
1196      * Nak for short sequence numbers shouldn't be sent, treat it
1197      * like a reject.
1198      */
1199     NAKCIVOID(CI_SSNHF, neg_ssnhf);
1200 
1201     /*
1202      * Nak of the endpoint discriminator option is not permitted,
1203      * treat it like a reject.
1204      */
1205     NAKCIENDP(CI_EPDISC, neg_endpoint);
1206 
1207     /*
1208      * There may be remaining CIs, if the peer is requesting negotiation
1209      * on an option that we didn't include in our request packet.
1210      * If we see an option that we requested, or one we've already seen
1211      * in this packet, then this packet is bad.
1212      * If we wanted to respond by starting to negotiate on the requested
1213      * option(s), we could, but we don't, because except for the
1214      * authentication type and quality protocol, if we are not negotiating
1215      * an option, it is because we were told not to.
1216      * For the authentication type, the Nak from the peer means
1217      * `let me authenticate myself with you' which is a bit pointless.
1218      * For the quality protocol, the Nak means `ask me to send you quality
1219      * reports', but if we didn't ask for them, we don't want them.
1220      * An option we don't recognize represents the peer asking to
1221      * negotiate some option we don't support, so ignore it.
1222      */
1223     while (len >= CILEN_VOID) {
1224 	GETCHAR(citype, p);
1225 	GETCHAR(cilen, p);
1226 	if (cilen < CILEN_VOID || (len -= cilen) < 0)
1227 	    goto bad;
1228 	next = p + cilen - 2;
1229 
1230 	switch (citype) {
1231 	case CI_MRU:
1232 	    if ((go->neg_mru && go->mru != DEFMRU)
1233 		|| no.neg_mru || cilen != CILEN_SHORT)
1234 		goto bad;
1235 	    GETSHORT(cishort, p);
1236 	    if (cishort < DEFMRU) {
1237 		try.neg_mru = 1;
1238 		try.mru = cishort;
1239 	    }
1240 	    break;
1241 	case CI_ASYNCMAP:
1242 	    if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1243 		|| no.neg_asyncmap || cilen != CILEN_LONG)
1244 		goto bad;
1245 	    break;
1246 	case CI_AUTHTYPE:
1247 	    if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap ||
1248 		go->neg_eap || no.neg_eap)
1249 		goto bad;
1250 	    break;
1251 	case CI_MAGICNUMBER:
1252 	    if (go->neg_magicnumber || no.neg_magicnumber ||
1253 		cilen != CILEN_LONG)
1254 		goto bad;
1255 	    break;
1256 	case CI_PCOMPRESSION:
1257 	    if (go->neg_pcompression || no.neg_pcompression
1258 		|| cilen != CILEN_VOID)
1259 		goto bad;
1260 	    break;
1261 	case CI_ACCOMPRESSION:
1262 	    if (go->neg_accompression || no.neg_accompression
1263 		|| cilen != CILEN_VOID)
1264 		goto bad;
1265 	    break;
1266 	case CI_QUALITY:
1267 	    if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1268 		goto bad;
1269 	    break;
1270 	case CI_MRRU:
1271 	    if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1272 		goto bad;
1273 	    break;
1274 	case CI_SSNHF:
1275 	    if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1276 		goto bad;
1277 	    try.neg_ssnhf = 1;
1278 	    break;
1279 	case CI_EPDISC:
1280 	    if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1281 		goto bad;
1282 	    break;
1283 	}
1284 	p = next;
1285     }
1286 
1287     /*
1288      * OK, the Nak is good.  Now we can update state.
1289      * If there are any options left we ignore them.
1290      */
1291     if (f->state != OPENED) {
1292 	if (looped_back) {
1293 	    if (++try.numloops >= lcp_loopbackfail) {
1294 		notice("Serial line is looped back.");
1295 		lcp_close(f->unit, "Loopback detected");
1296 		status = EXIT_LOOPBACK;
1297 	    }
1298 	} else
1299 	    try.numloops = 0;
1300 	*go = try;
1301     }
1302 
1303     return 1;
1304 
1305 bad:
1306     LCPDEBUG(("lcp_nakci: received bad Nak!"));
1307     return 0;
1308 }
1309 
1310 
1311 /*
1312  * lcp_rejci - Peer has Rejected some of our CIs.
1313  * This should not modify any state if the Reject is bad
1314  * or if LCP is in the OPENED state.
1315  *
1316  * Returns:
1317  *	0 - Reject was bad.
1318  *	1 - Reject was good.
1319  */
1320 static int
lcp_rejci(f,p,len)1321 lcp_rejci(f, p, len)
1322     fsm *f;
1323     u_char *p;
1324     int len;
1325 {
1326     lcp_options *go = &lcp_gotoptions[f->unit];
1327     u_char cichar;
1328     u_short cishort;
1329     u_int32_t cilong;
1330     lcp_options try;		/* options to request next time */
1331 
1332     try = *go;
1333 
1334     /*
1335      * Any Rejected CIs must be in exactly the same order that we sent.
1336      * Check packet length and CI length at each step.
1337      * If we find any deviations, then this packet is bad.
1338      */
1339 #define REJCIVOID(opt, neg) \
1340     if (go->neg && \
1341 	len >= CILEN_VOID && \
1342 	p[1] == CILEN_VOID && \
1343 	p[0] == opt) { \
1344 	len -= CILEN_VOID; \
1345 	INCPTR(CILEN_VOID, p); \
1346 	try.neg = 0; \
1347     }
1348 #define REJCISHORT(opt, neg, val) \
1349     if (go->neg && \
1350 	len >= CILEN_SHORT && \
1351 	p[1] == CILEN_SHORT && \
1352 	p[0] == opt) { \
1353 	len -= CILEN_SHORT; \
1354 	INCPTR(2, p); \
1355 	GETSHORT(cishort, p); \
1356 	/* Check rejected value. */ \
1357 	if (cishort != val) \
1358 	    goto bad; \
1359 	try.neg = 0; \
1360     }
1361 #define REJCICHAP(opt, neg, val) \
1362     if (go->neg && \
1363 	len >= CILEN_CHAP && \
1364 	p[1] == CILEN_CHAP && \
1365 	p[0] == opt) { \
1366 	len -= CILEN_CHAP; \
1367 	INCPTR(2, p); \
1368 	GETSHORT(cishort, p); \
1369 	GETCHAR(cichar, p); \
1370 	/* Check rejected value. */ \
1371 	if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1372 	    goto bad; \
1373 	try.neg = 0; \
1374 	try.neg_eap = try.neg_upap = 0; \
1375     }
1376 #define REJCILONG(opt, neg, val) \
1377     if (go->neg && \
1378 	len >= CILEN_LONG && \
1379 	p[1] == CILEN_LONG && \
1380 	p[0] == opt) { \
1381 	len -= CILEN_LONG; \
1382 	INCPTR(2, p); \
1383 	GETLONG(cilong, p); \
1384 	/* Check rejected value. */ \
1385 	if (cilong != val) \
1386 	    goto bad; \
1387 	try.neg = 0; \
1388     }
1389 #define REJCILQR(opt, neg, val) \
1390     if (go->neg && \
1391 	len >= CILEN_LQR && \
1392 	p[1] == CILEN_LQR && \
1393 	p[0] == opt) { \
1394 	len -= CILEN_LQR; \
1395 	INCPTR(2, p); \
1396 	GETSHORT(cishort, p); \
1397 	GETLONG(cilong, p); \
1398 	/* Check rejected value. */ \
1399 	if (cishort != PPP_LQR || cilong != val) \
1400 	    goto bad; \
1401 	try.neg = 0; \
1402     }
1403 #define REJCICBCP(opt, neg, val) \
1404     if (go->neg && \
1405 	len >= CILEN_CBCP && \
1406 	p[1] == CILEN_CBCP && \
1407 	p[0] == opt) { \
1408 	len -= CILEN_CBCP; \
1409 	INCPTR(2, p); \
1410 	GETCHAR(cichar, p); \
1411 	/* Check rejected value. */ \
1412 	if (cichar != val) \
1413 	    goto bad; \
1414 	try.neg = 0; \
1415     }
1416 #define REJCIENDP(opt, neg, class, val, vlen) \
1417     if (go->neg && \
1418 	len >= CILEN_CHAR + vlen && \
1419 	p[0] == opt && \
1420 	p[1] == CILEN_CHAR + vlen) { \
1421 	int i; \
1422 	len -= CILEN_CHAR + vlen; \
1423 	INCPTR(2, p); \
1424 	GETCHAR(cichar, p); \
1425 	if (cichar != class) \
1426 	    goto bad; \
1427 	for (i = 0; i < vlen; ++i) { \
1428 	    GETCHAR(cichar, p); \
1429 	    if (cichar != val[i]) \
1430 		goto bad; \
1431 	} \
1432 	try.neg = 0; \
1433     }
1434 
1435     REJCISHORT(CI_MRU, neg_mru, go->mru);
1436     REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1437     REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
1438     if (!go->neg_eap) {
1439 	REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
1440 	if (!go->neg_chap) {
1441 	    REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1442 	}
1443     }
1444     REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1445     REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1446     REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1447     REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1448     REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1449     REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1450     REJCIVOID(CI_SSNHF, neg_ssnhf);
1451     REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class,
1452 	      go->endpoint.value, go->endpoint.length);
1453 
1454     /*
1455      * If there are any remaining CIs, then this packet is bad.
1456      */
1457     if (len != 0)
1458 	goto bad;
1459     /*
1460      * Now we can update state.
1461      */
1462     if (f->state != OPENED)
1463 	*go = try;
1464     return 1;
1465 
1466 bad:
1467     LCPDEBUG(("lcp_rejci: received bad Reject!"));
1468     return 0;
1469 }
1470 
1471 
1472 /*
1473  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1474  *
1475  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1476  * appropriately.  If reject_if_disagree is non-zero, doesn't return
1477  * CONFNAK; returns CONFREJ if it can't return CONFACK.
1478  */
1479 static int
lcp_reqci(f,inp,lenp,reject_if_disagree)1480 lcp_reqci(f, inp, lenp, reject_if_disagree)
1481     fsm *f;
1482     u_char *inp;		/* Requested CIs */
1483     int *lenp;			/* Length of requested CIs */
1484     int reject_if_disagree;
1485 {
1486     lcp_options *go = &lcp_gotoptions[f->unit];
1487     lcp_options *ho = &lcp_hisoptions[f->unit];
1488     lcp_options *ao = &lcp_allowoptions[f->unit];
1489     u_char *cip, *next;		/* Pointer to current and next CIs */
1490     int cilen, citype, cichar;	/* Parsed len, type, char value */
1491     u_short cishort;		/* Parsed short value */
1492     u_int32_t cilong;		/* Parse long value */
1493     int rc = CONFACK;		/* Final packet return code */
1494     int orc;			/* Individual option return code */
1495     u_char *p;			/* Pointer to next char to parse */
1496     u_char *rejp;		/* Pointer to next char in reject frame */
1497     u_char *nakp;		/* Pointer to next char in Nak frame */
1498     int l = *lenp;		/* Length left */
1499 
1500     /*
1501      * Reset all his options.
1502      */
1503     BZERO(ho, sizeof(*ho));
1504 
1505     /*
1506      * Process all his options.
1507      */
1508     next = inp;
1509     nakp = nak_buffer;
1510     rejp = inp;
1511     while (l) {
1512 	orc = CONFACK;			/* Assume success */
1513 	cip = p = next;			/* Remember begining of CI */
1514 	if (l < 2 ||			/* Not enough data for CI header or */
1515 	    p[1] < 2 ||			/*  CI length too small or */
1516 	    p[1] > l) {			/*  CI length too big? */
1517 	    LCPDEBUG(("lcp_reqci: bad CI length!"));
1518 	    orc = CONFREJ;		/* Reject bad CI */
1519 	    cilen = l;			/* Reject till end of packet */
1520 	    l = 0;			/* Don't loop again */
1521 	    citype = 0;
1522 	    goto endswitch;
1523 	}
1524 	GETCHAR(citype, p);		/* Parse CI type */
1525 	GETCHAR(cilen, p);		/* Parse CI length */
1526 	l -= cilen;			/* Adjust remaining length */
1527 	next += cilen;			/* Step to next CI */
1528 
1529 	switch (citype) {		/* Check CI type */
1530 	case CI_MRU:
1531 	    if (!ao->neg_mru ||		/* Allow option? */
1532 		cilen != CILEN_SHORT) {	/* Check CI length */
1533 		orc = CONFREJ;		/* Reject CI */
1534 		break;
1535 	    }
1536 	    GETSHORT(cishort, p);	/* Parse MRU */
1537 
1538 	    /*
1539 	     * He must be able to receive at least our minimum.
1540 	     * No need to check a maximum.  If he sends a large number,
1541 	     * we'll just ignore it.
1542 	     */
1543 	    if (cishort < MINMRU) {
1544 		orc = CONFNAK;		/* Nak CI */
1545 		PUTCHAR(CI_MRU, nakp);
1546 		PUTCHAR(CILEN_SHORT, nakp);
1547 		PUTSHORT(MINMRU, nakp);	/* Give him a hint */
1548 		break;
1549 	    }
1550 	    ho->neg_mru = 1;		/* Remember he sent MRU */
1551 	    ho->mru = cishort;		/* And remember value */
1552 	    break;
1553 
1554 	case CI_ASYNCMAP:
1555 	    if (!ao->neg_asyncmap ||
1556 		cilen != CILEN_LONG) {
1557 		orc = CONFREJ;
1558 		break;
1559 	    }
1560 	    GETLONG(cilong, p);
1561 
1562 	    /*
1563 	     * Asyncmap must have set at least the bits
1564 	     * which are set in lcp_allowoptions[unit].asyncmap.
1565 	     */
1566 	    if ((ao->asyncmap & ~cilong) != 0) {
1567 		orc = CONFNAK;
1568 		PUTCHAR(CI_ASYNCMAP, nakp);
1569 		PUTCHAR(CILEN_LONG, nakp);
1570 		PUTLONG(ao->asyncmap | cilong, nakp);
1571 		break;
1572 	    }
1573 	    ho->neg_asyncmap = 1;
1574 	    ho->asyncmap = cilong;
1575 	    break;
1576 
1577 	case CI_AUTHTYPE:
1578 	    if (cilen < CILEN_SHORT ||
1579 		!(ao->neg_upap || ao->neg_chap || ao->neg_eap)) {
1580 		/*
1581 		 * Reject the option if we're not willing to authenticate.
1582 		 */
1583 		dbglog("No auth is possible");
1584 		orc = CONFREJ;
1585 		break;
1586 	    }
1587 	    GETSHORT(cishort, p);
1588 
1589 	    /*
1590 	     * Authtype must be PAP, CHAP, or EAP.
1591 	     *
1592 	     * Note: if more than one of ao->neg_upap, ao->neg_chap, and
1593 	     * ao->neg_eap are set, and the peer sends a Configure-Request
1594 	     * with two or more authenticate-protocol requests, then we will
1595 	     * reject the second request.
1596 	     * Whether we end up doing CHAP, UPAP, or EAP depends then on
1597 	     * the ordering of the CIs in the peer's Configure-Request.
1598              */
1599 
1600 	    if (cishort == PPP_PAP) {
1601 		/* we've already accepted CHAP or EAP */
1602 		if (ho->neg_chap || ho->neg_eap ||
1603 		    cilen != CILEN_SHORT) {
1604 		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1605 		    orc = CONFREJ;
1606 		    break;
1607 		}
1608 		if (!ao->neg_upap) {	/* we don't want to do PAP */
1609 		    orc = CONFNAK;	/* NAK it and suggest CHAP or EAP */
1610 		    PUTCHAR(CI_AUTHTYPE, nakp);
1611 		    if (ao->neg_eap) {
1612 			PUTCHAR(CILEN_SHORT, nakp);
1613 			PUTSHORT(PPP_EAP, nakp);
1614 		    } else {
1615 			PUTCHAR(CILEN_CHAP, nakp);
1616 			PUTSHORT(PPP_CHAP, nakp);
1617 			PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
1618 		    }
1619 		    break;
1620 		}
1621 		ho->neg_upap = 1;
1622 		break;
1623 	    }
1624 	    if (cishort == PPP_CHAP) {
1625 		/* we've already accepted PAP or EAP */
1626 		if (ho->neg_upap || ho->neg_eap ||
1627 		    cilen != CILEN_CHAP) {
1628 		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
1629 		    orc = CONFREJ;
1630 		    break;
1631 		}
1632 		if (!ao->neg_chap) {	/* we don't want to do CHAP */
1633 		    orc = CONFNAK;	/* NAK it and suggest EAP or PAP */
1634 		    PUTCHAR(CI_AUTHTYPE, nakp);
1635 		    PUTCHAR(CILEN_SHORT, nakp);
1636 		    if (ao->neg_eap) {
1637 			PUTSHORT(PPP_EAP, nakp);
1638 		    } else {
1639 			PUTSHORT(PPP_PAP, nakp);
1640 		    }
1641 		    break;
1642 		}
1643 		GETCHAR(cichar, p);	/* get digest type */
1644 		if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) {
1645 		    /*
1646 		     * We can't/won't do the requested type,
1647 		     * suggest something else.
1648 		     */
1649 		    orc = CONFNAK;
1650 		    PUTCHAR(CI_AUTHTYPE, nakp);
1651 		    PUTCHAR(CILEN_CHAP, nakp);
1652 		    PUTSHORT(PPP_CHAP, nakp);
1653 		    PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
1654 		    break;
1655 		}
1656 		ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */
1657 		ho->neg_chap = 1;
1658 		break;
1659 	    }
1660 	    if (cishort == PPP_EAP) {
1661 		/* we've already accepted CHAP or PAP */
1662 		if (ho->neg_chap || ho->neg_upap || cilen != CILEN_SHORT) {
1663 		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
1664 		    orc = CONFREJ;
1665 		    break;
1666 		}
1667 		if (!ao->neg_eap) {	/* we don't want to do EAP */
1668 		    orc = CONFNAK;	/* NAK it and suggest CHAP or PAP */
1669 		    PUTCHAR(CI_AUTHTYPE, nakp);
1670 		    if (ao->neg_chap) {
1671 			PUTCHAR(CILEN_CHAP, nakp);
1672 			PUTSHORT(PPP_CHAP, nakp);
1673 			PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
1674 		    } else {
1675 			PUTCHAR(CILEN_SHORT, nakp);
1676 			PUTSHORT(PPP_PAP, nakp);
1677 		    }
1678 		    break;
1679 		}
1680 		ho->neg_eap = 1;
1681 		break;
1682 	    }
1683 
1684 	    /*
1685 	     * We don't recognize the protocol they're asking for.
1686 	     * Nak it with something we're willing to do.
1687 	     * (At this point we know ao->neg_upap || ao->neg_chap ||
1688 	     * ao->neg_eap.)
1689 	     */
1690 	    orc = CONFNAK;
1691 	    PUTCHAR(CI_AUTHTYPE, nakp);
1692 	    if (ao->neg_eap) {
1693 		PUTCHAR(CILEN_SHORT, nakp);
1694 		PUTSHORT(PPP_EAP, nakp);
1695 	    } else if (ao->neg_chap) {
1696 		PUTCHAR(CILEN_CHAP, nakp);
1697 		PUTSHORT(PPP_CHAP, nakp);
1698 		PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
1699 	    } else {
1700 		PUTCHAR(CILEN_SHORT, nakp);
1701 		PUTSHORT(PPP_PAP, nakp);
1702 	    }
1703 	    break;
1704 
1705 	case CI_QUALITY:
1706 	    if (!ao->neg_lqr ||
1707 		cilen != CILEN_LQR) {
1708 		orc = CONFREJ;
1709 		break;
1710 	    }
1711 
1712 	    GETSHORT(cishort, p);
1713 	    GETLONG(cilong, p);
1714 
1715 	    /*
1716 	     * Check the protocol and the reporting period.
1717 	     * XXX When should we Nak this, and what with?
1718 	     */
1719 	    if (cishort != PPP_LQR) {
1720 		orc = CONFNAK;
1721 		PUTCHAR(CI_QUALITY, nakp);
1722 		PUTCHAR(CILEN_LQR, nakp);
1723 		PUTSHORT(PPP_LQR, nakp);
1724 		PUTLONG(ao->lqr_period, nakp);
1725 		break;
1726 	    }
1727 	    break;
1728 
1729 	case CI_MAGICNUMBER:
1730 	    if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
1731 		cilen != CILEN_LONG) {
1732 		orc = CONFREJ;
1733 		break;
1734 	    }
1735 	    GETLONG(cilong, p);
1736 
1737 	    /*
1738 	     * He must have a different magic number.
1739 	     */
1740 	    if (go->neg_magicnumber &&
1741 		cilong == go->magicnumber) {
1742 		cilong = magic();	/* Don't put magic() inside macro! */
1743 		orc = CONFNAK;
1744 		PUTCHAR(CI_MAGICNUMBER, nakp);
1745 		PUTCHAR(CILEN_LONG, nakp);
1746 		PUTLONG(cilong, nakp);
1747 		break;
1748 	    }
1749 	    ho->neg_magicnumber = 1;
1750 	    ho->magicnumber = cilong;
1751 	    break;
1752 
1753 
1754 	case CI_PCOMPRESSION:
1755 	    if (!ao->neg_pcompression ||
1756 		cilen != CILEN_VOID) {
1757 		orc = CONFREJ;
1758 		break;
1759 	    }
1760 	    ho->neg_pcompression = 1;
1761 	    break;
1762 
1763 	case CI_ACCOMPRESSION:
1764 	    if (!ao->neg_accompression ||
1765 		cilen != CILEN_VOID) {
1766 		orc = CONFREJ;
1767 		break;
1768 	    }
1769 	    ho->neg_accompression = 1;
1770 	    break;
1771 
1772 	case CI_MRRU:
1773 	    if (!ao->neg_mrru || !multilink ||
1774 		cilen != CILEN_SHORT) {
1775 		orc = CONFREJ;
1776 		break;
1777 	    }
1778 
1779 	    GETSHORT(cishort, p);
1780 	    /* possibly should insist on a minimum/maximum MRRU here */
1781 	    ho->neg_mrru = 1;
1782 	    ho->mrru = cishort;
1783 	    break;
1784 
1785 	case CI_SSNHF:
1786 	    if (!ao->neg_ssnhf || !multilink ||
1787 		cilen != CILEN_VOID) {
1788 		orc = CONFREJ;
1789 		break;
1790 	    }
1791 	    ho->neg_ssnhf = 1;
1792 	    break;
1793 
1794 	case CI_EPDISC:
1795 	    if (!ao->neg_endpoint ||
1796 		cilen < CILEN_CHAR ||
1797 		cilen > CILEN_CHAR + MAX_ENDP_LEN) {
1798 		orc = CONFREJ;
1799 		break;
1800 	    }
1801 	    GETCHAR(cichar, p);
1802 	    cilen -= CILEN_CHAR;
1803 	    ho->neg_endpoint = 1;
1804 	    ho->endpoint.class = cichar;
1805 	    ho->endpoint.length = cilen;
1806 	    BCOPY(p, ho->endpoint.value, cilen);
1807 	    INCPTR(cilen, p);
1808 	    break;
1809 
1810 	default:
1811 	    LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
1812 	    orc = CONFREJ;
1813 	    break;
1814 	}
1815 
1816 endswitch:
1817 	if (orc == CONFACK &&		/* Good CI */
1818 	    rc != CONFACK)		/*  but prior CI wasnt? */
1819 	    continue;			/* Don't send this one */
1820 
1821 	if (orc == CONFNAK) {		/* Nak this CI? */
1822 	    if (reject_if_disagree	/* Getting fed up with sending NAKs? */
1823 		&& citype != CI_MAGICNUMBER) {
1824 		orc = CONFREJ;		/* Get tough if so */
1825 	    } else {
1826 		if (rc == CONFREJ)	/* Rejecting prior CI? */
1827 		    continue;		/* Don't send this one */
1828 		rc = CONFNAK;
1829 	    }
1830 	}
1831 	if (orc == CONFREJ) {		/* Reject this CI */
1832 	    rc = CONFREJ;
1833 	    if (cip != rejp)		/* Need to move rejected CI? */
1834 		BCOPY(cip, rejp, cilen); /* Move it */
1835 	    INCPTR(cilen, rejp);	/* Update output pointer */
1836 	}
1837     }
1838 
1839     /*
1840      * If we wanted to send additional NAKs (for unsent CIs), the
1841      * code would go here.  The extra NAKs would go at *nakp.
1842      * At present there are no cases where we want to ask the
1843      * peer to negotiate an option.
1844      */
1845 
1846     switch (rc) {
1847     case CONFACK:
1848 	*lenp = next - inp;
1849 	break;
1850     case CONFNAK:
1851 	/*
1852 	 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
1853 	 */
1854 	*lenp = nakp - nak_buffer;
1855 	BCOPY(nak_buffer, inp, *lenp);
1856 	break;
1857     case CONFREJ:
1858 	*lenp = rejp - inp;
1859 	break;
1860     }
1861 
1862     LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
1863     return (rc);			/* Return final code */
1864 }
1865 
1866 
1867 /*
1868  * lcp_up - LCP has come UP.
1869  */
1870 static void
lcp_up(f)1871 lcp_up(f)
1872     fsm *f;
1873 {
1874     lcp_options *wo = &lcp_wantoptions[f->unit];
1875     lcp_options *ho = &lcp_hisoptions[f->unit];
1876     lcp_options *go = &lcp_gotoptions[f->unit];
1877     lcp_options *ao = &lcp_allowoptions[f->unit];
1878     int mtu, mru;
1879 
1880     if (!go->neg_magicnumber)
1881 	go->magicnumber = 0;
1882     if (!ho->neg_magicnumber)
1883 	ho->magicnumber = 0;
1884 
1885     /*
1886      * Set our MTU to the smaller of the MTU we wanted and
1887      * the MRU our peer wanted.  If we negotiated an MRU,
1888      * set our MRU to the larger of value we wanted and
1889      * the value we got in the negotiation.
1890      * Note on the MTU: the link MTU can be the MRU the peer wanted,
1891      * the interface MTU is set to the lowest of that, the
1892      * MTU we want to use, and our link MRU.
1893      */
1894     mtu = ho->neg_mru? ho->mru: PPP_MRU;
1895     mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU;
1896 #ifdef HAVE_MULTILINK
1897     if (!(multilink && go->neg_mrru && ho->neg_mrru))
1898 #endif /* HAVE_MULTILINK */
1899 	netif_set_mtu(f->unit, MIN(MIN(mtu, mru), ao->mru));
1900     ppp_send_config(f->unit, mtu,
1901 		    (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
1902 		    ho->neg_pcompression, ho->neg_accompression);
1903     ppp_recv_config(f->unit, mru,
1904 		    (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
1905 		    go->neg_pcompression, go->neg_accompression);
1906 
1907     if (ho->neg_mru)
1908 	peer_mru[f->unit] = ho->mru;
1909 
1910     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
1911 
1912     link_established(f->unit);
1913 }
1914 
1915 
1916 /*
1917  * lcp_down - LCP has gone DOWN.
1918  *
1919  * Alert other protocols.
1920  */
1921 static void
lcp_down(f)1922 lcp_down(f)
1923     fsm *f;
1924 {
1925     lcp_options *go = &lcp_gotoptions[f->unit];
1926 
1927     lcp_echo_lowerdown(f->unit);
1928 
1929     link_down(f->unit);
1930 
1931     ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
1932     ppp_recv_config(f->unit, PPP_MRU,
1933 		    (go->neg_asyncmap? go->asyncmap: 0xffffffff),
1934 		    go->neg_pcompression, go->neg_accompression);
1935     peer_mru[f->unit] = PPP_MRU;
1936 }
1937 
1938 
1939 /*
1940  * lcp_starting - LCP needs the lower layer up.
1941  */
1942 static void
lcp_starting(f)1943 lcp_starting(f)
1944     fsm *f;
1945 {
1946     link_required(f->unit);
1947 }
1948 
1949 
1950 /*
1951  * lcp_finished - LCP has finished with the lower layer.
1952  */
1953 static void
lcp_finished(f)1954 lcp_finished(f)
1955     fsm *f;
1956 {
1957     link_terminated(f->unit);
1958 }
1959 
1960 
1961 /*
1962  * lcp_printpkt - print the contents of an LCP packet.
1963  */
1964 static char *lcp_codenames[] = {
1965     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1966     "TermReq", "TermAck", "CodeRej", "ProtRej",
1967     "EchoReq", "EchoRep", "DiscReq"
1968 };
1969 
1970 static int
lcp_printpkt(p,plen,printer,arg)1971 lcp_printpkt(p, plen, printer, arg)
1972     u_char *p;
1973     int plen;
1974     void (*printer) __P((void *, char *, ...));
1975     void *arg;
1976 {
1977     int code, id, len, olen, i;
1978     u_char *pstart, *optend;
1979     u_short cishort;
1980     u_int32_t cilong;
1981 
1982     if (plen < HEADERLEN)
1983 	return 0;
1984     pstart = p;
1985     GETCHAR(code, p);
1986     GETCHAR(id, p);
1987     GETSHORT(len, p);
1988     if (len < HEADERLEN || len > plen)
1989 	return 0;
1990 
1991     if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
1992 	printer(arg, " %s", lcp_codenames[code-1]);
1993     else
1994 	printer(arg, " code=0x%x", code);
1995     printer(arg, " id=0x%x", id);
1996     len -= HEADERLEN;
1997     switch (code) {
1998     case CONFREQ:
1999     case CONFACK:
2000     case CONFNAK:
2001     case CONFREJ:
2002 	/* print option list */
2003 	while (len >= 2) {
2004 	    GETCHAR(code, p);
2005 	    GETCHAR(olen, p);
2006 	    p -= 2;
2007 	    if (olen < 2 || olen > len) {
2008 		break;
2009 	    }
2010 	    printer(arg, " <");
2011 	    len -= olen;
2012 	    optend = p + olen;
2013 	    switch (code) {
2014 	    case CI_MRU:
2015 		if (olen == CILEN_SHORT) {
2016 		    p += 2;
2017 		    GETSHORT(cishort, p);
2018 		    printer(arg, "mru %d", cishort);
2019 		}
2020 		break;
2021 	    case CI_ASYNCMAP:
2022 		if (olen == CILEN_LONG) {
2023 		    p += 2;
2024 		    GETLONG(cilong, p);
2025 		    printer(arg, "asyncmap 0x%x", cilong);
2026 		}
2027 		break;
2028 	    case CI_AUTHTYPE:
2029 		if (olen >= CILEN_SHORT) {
2030 		    p += 2;
2031 		    printer(arg, "auth ");
2032 		    GETSHORT(cishort, p);
2033 		    switch (cishort) {
2034 		    case PPP_PAP:
2035 			printer(arg, "pap");
2036 			break;
2037 		    case PPP_CHAP:
2038 			printer(arg, "chap");
2039 			if (p < optend) {
2040 			    switch (*p) {
2041 			    case CHAP_MD5:
2042 				printer(arg, " MD5");
2043 				++p;
2044 				break;
2045 #ifdef CHAPMS
2046 			    case CHAP_MICROSOFT:
2047 				printer(arg, " MS");
2048 				++p;
2049 				break;
2050 
2051 			    case CHAP_MICROSOFT_V2:
2052 				printer(arg, " MS-v2");
2053 				++p;
2054 				break;
2055 #endif
2056 			    }
2057 			}
2058 			break;
2059 		    case PPP_EAP:
2060 			printer(arg, "eap");
2061 			break;
2062 		    default:
2063 			printer(arg, "0x%x", cishort);
2064 		    }
2065 		}
2066 		break;
2067 	    case CI_QUALITY:
2068 		if (olen >= CILEN_SHORT) {
2069 		    p += 2;
2070 		    printer(arg, "quality ");
2071 		    GETSHORT(cishort, p);
2072 		    switch (cishort) {
2073 		    case PPP_LQR:
2074 			printer(arg, "lqr");
2075 			break;
2076 		    default:
2077 			printer(arg, "0x%x", cishort);
2078 		    }
2079 		}
2080 		break;
2081 	    case CI_CALLBACK:
2082 		if (olen >= CILEN_CHAR) {
2083 		    p += 2;
2084 		    printer(arg, "callback ");
2085 		    GETCHAR(cishort, p);
2086 		    switch (cishort) {
2087 		    case CBCP_OPT:
2088 			printer(arg, "CBCP");
2089 			break;
2090 		    default:
2091 			printer(arg, "0x%x", cishort);
2092 		    }
2093 		}
2094 		break;
2095 	    case CI_MAGICNUMBER:
2096 		if (olen == CILEN_LONG) {
2097 		    p += 2;
2098 		    GETLONG(cilong, p);
2099 		    printer(arg, "magic 0x%x", cilong);
2100 		}
2101 		break;
2102 	    case CI_PCOMPRESSION:
2103 		if (olen == CILEN_VOID) {
2104 		    p += 2;
2105 		    printer(arg, "pcomp");
2106 		}
2107 		break;
2108 	    case CI_ACCOMPRESSION:
2109 		if (olen == CILEN_VOID) {
2110 		    p += 2;
2111 		    printer(arg, "accomp");
2112 		}
2113 		break;
2114 	    case CI_MRRU:
2115 		if (olen == CILEN_SHORT) {
2116 		    p += 2;
2117 		    GETSHORT(cishort, p);
2118 		    printer(arg, "mrru %d", cishort);
2119 		}
2120 		break;
2121 	    case CI_SSNHF:
2122 		if (olen == CILEN_VOID) {
2123 		    p += 2;
2124 		    printer(arg, "ssnhf");
2125 		}
2126 		break;
2127 	    case CI_EPDISC:
2128 #ifdef HAVE_MULTILINK
2129 		if (olen >= CILEN_CHAR) {
2130 		    struct epdisc epd;
2131 		    p += 2;
2132 		    GETCHAR(epd.class, p);
2133 		    epd.length = olen - CILEN_CHAR;
2134 		    if (epd.length > MAX_ENDP_LEN)
2135 			epd.length = MAX_ENDP_LEN;
2136 		    if (epd.length > 0) {
2137 			BCOPY(p, epd.value, epd.length);
2138 			p += epd.length;
2139 		    }
2140 		    printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
2141 		}
2142 #else
2143 		printer(arg, "endpoint");
2144 #endif
2145 		break;
2146 	    }
2147 	    while (p < optend) {
2148 		GETCHAR(code, p);
2149 		printer(arg, " %.2x", code);
2150 	    }
2151 	    printer(arg, ">");
2152 	}
2153 	break;
2154 
2155     case TERMACK:
2156     case TERMREQ:
2157 	if (len > 0 && *p >= ' ' && *p < 0x7f) {
2158 	    printer(arg, " ");
2159 	    print_string((char *)p, len, printer, arg);
2160 	    p += len;
2161 	    len = 0;
2162 	}
2163 	break;
2164 
2165     case ECHOREQ:
2166     case ECHOREP:
2167     case DISCREQ:
2168 	if (len >= 4) {
2169 	    GETLONG(cilong, p);
2170 	    printer(arg, " magic=0x%x", cilong);
2171 	    p += 4;
2172 	    len -= 4;
2173 	}
2174 	break;
2175     }
2176 
2177     /* print the rest of the bytes in the packet */
2178     for (i = 0; i < len && i < 32; ++i) {
2179 	GETCHAR(code, p);
2180 	printer(arg, " %.2x", code);
2181     }
2182     if (i < len) {
2183 	printer(arg, " ...");
2184 	p += len - i;
2185     }
2186 
2187     return p - pstart;
2188 }
2189 
2190 /*
2191  * Time to shut down the link because there is nothing out there.
2192  */
2193 
2194 static
LcpLinkFailure(f)2195 void LcpLinkFailure (f)
2196     fsm *f;
2197 {
2198     if (f->state == OPENED) {
2199 	info("No response to %d echo-requests", lcp_echos_pending);
2200         notice("Serial link appears to be disconnected.");
2201         lcp_close(f->unit, "Peer not responding");
2202 	status = EXIT_PEER_DEAD;
2203     }
2204 }
2205 
2206 /*
2207  * Timer expired for the LCP echo requests from this process.
2208  */
2209 
2210 static void
LcpEchoCheck(f)2211 LcpEchoCheck (f)
2212     fsm *f;
2213 {
2214     LcpSendEchoRequest (f);
2215     if (f->state != OPENED)
2216 	return;
2217 
2218     /*
2219      * Start the timer for the next interval.
2220      */
2221     if (lcp_echo_timer_running)
2222 	warn("assertion lcp_echo_timer_running==0 failed");
2223     TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
2224     lcp_echo_timer_running = 1;
2225 }
2226 
2227 /*
2228  * LcpEchoTimeout - Timer expired on the LCP echo
2229  */
2230 
2231 static void
LcpEchoTimeout(arg)2232 LcpEchoTimeout (arg)
2233     void *arg;
2234 {
2235     if (lcp_echo_timer_running != 0) {
2236         lcp_echo_timer_running = 0;
2237         LcpEchoCheck ((fsm *) arg);
2238     }
2239 }
2240 
2241 /*
2242  * LcpEchoReply - LCP has received a reply to the echo
2243  */
2244 
2245 static void
lcp_received_echo_reply(f,id,inp,len)2246 lcp_received_echo_reply (f, id, inp, len)
2247     fsm *f;
2248     int id;
2249     u_char *inp;
2250     int len;
2251 {
2252     u_int32_t magic;
2253 
2254     /* Check the magic number - don't count replies from ourselves. */
2255     if (len < 4) {
2256 	dbglog("lcp: received short Echo-Reply, length %d", len);
2257 	return;
2258     }
2259     GETLONG(magic, inp);
2260     if (lcp_gotoptions[f->unit].neg_magicnumber
2261 	&& magic == lcp_gotoptions[f->unit].magicnumber) {
2262 	warn("appear to have received our own echo-reply!");
2263 	return;
2264     }
2265 
2266     /* Reset the number of outstanding echo frames */
2267     lcp_echos_pending = 0;
2268 }
2269 
2270 /*
2271  * LcpSendEchoRequest - Send an echo request frame to the peer
2272  */
2273 
2274 static void
LcpSendEchoRequest(f)2275 LcpSendEchoRequest (f)
2276     fsm *f;
2277 {
2278     u_int32_t lcp_magic;
2279     u_char pkt[4], *pktp;
2280 
2281     /*
2282      * Detect the failure of the peer at this point.
2283      */
2284     if (lcp_echo_fails != 0) {
2285         if (lcp_echos_pending >= lcp_echo_fails) {
2286             LcpLinkFailure(f);
2287 	    lcp_echos_pending = 0;
2288 	}
2289     }
2290 
2291     /*
2292      * Make and send the echo request frame.
2293      */
2294     if (f->state == OPENED) {
2295         lcp_magic = lcp_gotoptions[f->unit].magicnumber;
2296 	pktp = pkt;
2297 	PUTLONG(lcp_magic, pktp);
2298         fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
2299 	++lcp_echos_pending;
2300     }
2301 }
2302 
2303 /*
2304  * lcp_echo_lowerup - Start the timer for the LCP frame
2305  */
2306 
2307 static void
lcp_echo_lowerup(unit)2308 lcp_echo_lowerup (unit)
2309     int unit;
2310 {
2311     fsm *f = &lcp_fsm[unit];
2312 
2313     /* Clear the parameters for generating echo frames */
2314     lcp_echos_pending      = 0;
2315     lcp_echo_number        = 0;
2316     lcp_echo_timer_running = 0;
2317 
2318     /* If a timeout interval is specified then start the timer */
2319     if (lcp_echo_interval != 0)
2320         LcpEchoCheck (f);
2321 }
2322 
2323 /*
2324  * lcp_echo_lowerdown - Stop the timer for the LCP frame
2325  */
2326 
2327 static void
lcp_echo_lowerdown(unit)2328 lcp_echo_lowerdown (unit)
2329     int unit;
2330 {
2331     fsm *f = &lcp_fsm[unit];
2332 
2333     if (lcp_echo_timer_running != 0) {
2334         UNTIMEOUT (LcpEchoTimeout, f);
2335         lcp_echo_timer_running = 0;
2336     }
2337 }
2338