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