xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.bin/pppd/lcp.c (revision 8c69cc8fbe729fa7b091e901c4b50508ccc6bb33)
1 /*
2  * lcp.c - PPP Link Control Protocol.
3  *
4  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
5  * Use is subject to license terms.
6  *
7  * Copyright (c) 1989 Carnegie Mellon University.
8  * All rights reserved.
9  *
10  * Copyright (c) 2016 by Delphix. All rights reserved.
11  *
12  * Redistribution and use in source and binary forms are permitted
13  * provided that the above copyright notice and this paragraph are
14  * duplicated in all such forms and that any documentation,
15  * advertising materials, and other materials related to such
16  * distribution and use acknowledge that the software was developed
17  * by Carnegie Mellon University.  The name of the
18  * University may not be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
22  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  */
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #if defined(CHAPMS) || defined(CHAPMSV2)
30 #ifdef HAVE_CRYPT_H
31 #include <crypt.h>
32 #endif
33 #ifndef USE_CRYPT
34 #include <des.h>
35 #endif
36 #ifdef SOL2
37 #include <errno.h>
38 #endif
39 #endif
40 
41 #include "pppd.h"
42 #include "fsm.h"
43 #include "lcp.h"
44 #include "chap.h"
45 #include "magic.h"
46 #include "patchlevel.h"
47 
48 /*
49  * Special failure codes for logging link failure reasons.
50  */
51 bool peer_nak_auth;		/* Peer sent nak for our auth request */
52 u_short nak_auth_orig;		/* Auth proto peer naked */
53 u_short nak_auth_proto;		/* Auth proto peer suggested instead */
54 bool unsolicited_nak_auth;	/* Peer asked us to authenticate */
55 u_short unsolicit_auth_proto;	/* Auth proto peer wants */
56 bool peer_reject_auth;		/* Peer sent reject for auth */
57 u_short reject_auth_proto;	/* Protocol that peer rejected */
58 bool rejected_peers_auth;	/* We sent a reject to the peer */
59 u_short rejected_auth_proto;	/* Protocol that peer wanted to use */
60 bool naked_peers_auth;		/* We sent a nak to the peer */
61 u_short naked_auth_orig;	/* Protocol that we wanted to use */
62 u_short naked_auth_proto;	/* Protocol that peer wants us to use */
63 
64 /*
65  * LCP-related command-line options.
66  */
67 int	lcp_echo_interval = 0; 	/* Interval between LCP echo-requests */
68 int	lcp_echo_fails = 0;	/* Tolerance to unanswered echo-requests */
69 bool	lax_recv = 0;		/* accept control chars in asyncmap */
70 static int use_accm_test = 2;	/* use big echo-requests to check ACCM */
71 #define	ACCM_TEST_FAILS	5
72 
73 #define _tostr2(x)	#x
74 #define _tostr(x)	_tostr2(x)
75 static char identstr[256] =	/* Identification string */
76 	"ppp-" VERSION "." _tostr(PATCHLEVEL) IMPLEMENTATION;
77 static int noident = 0;		/* 1 to disable; 2 to reject */
78 static int sentident = 0;	/* counts the # of ident codes sent */
79 
80 /* set if we're allowed to send an unsolicited Configure-Nak for MRU. */
81 static bool unsolicit_mru;
82 
83 static int setescape __P((char **, option_t *));
84 
85 static bool do_msft_workaround = 1;
86 static int setasyncmap __P((char **, option_t *));
87 
88 bool	noendpoint = 0;		/* don't send/accept endpoint discriminator */
89 static int setendpoint __P((char **, option_t *));
90 
91 static char *callback_strings[] = {
92 	"auth", "dialstring", "location", "E.164", "X.500", "", "CBCP", NULL
93 };
94 
95 /* This is used in packet printing even if NEGOTIATE_FCS isn't enabled */
96 static char *fcsalt_strings[] = {
97 	"null", "crc16", "crc32", NULL
98 };
99 
100 #ifdef NEGOTIATE_FCS
101 static int setfcsallow __P((char **, option_t *));
102 static int setfcswant __P((char **, option_t *));
103 #endif
104 
105 /* Backward compatibility for Linux */
106 #ifndef PPP_MAXMRU
107 #define	PPP_MTU		1500	/* Default MTU (size of Info field) */
108 #define	PPP_MAXMTU	65535 - (PPP_HDRLEN + PPP_FCSLEN)
109 #define	PPP_MINMTU	64
110 #define	PPP_MAXMRU	65000	/* Largest MRU we allow */
111 #define	PPP_MINMRU	128
112 #endif
113 
114 static option_t lcp_option_list[] = {
115     /* LCP options */
116     { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
117       "Disable address/control compression",
118       OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
119     { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
120       "Disable address/control compression",
121       OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
122     { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap,
123       "Disable asyncmap negotiation",
124       OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
125     { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap,
126       "Disable asyncmap negotiation",
127       OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
128     { "asyncmap", o_special, (void *)setasyncmap,
129       "Set asyncmap (for received packets)" },
130     { "-as", o_special, (void *)setasyncmap,
131       "Set asyncmap (for received packets)" },
132     { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
133       "Disable magic number option (looped-back line detect)",
134       OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
135     { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
136       "Disable magic number option (looped-back line detect)",
137       OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
138     { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
139       "Disable MRU negotiation (use default 1500)",
140       OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
141     { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
142       "Disable MRU negotiation (use default 1500)",
143       OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
144     { "mru", o_int, &lcp_wantoptions[0].mru,
145       "Set MRU (maximum received packet size) for negotiation",
146       OPT_LIMITS, &lcp_wantoptions[0].neg_mru, PPP_MAXMRU, PPP_MINMRU },
147     { "mtu", o_int, &lcp_allowoptions[0].mru,
148       "Set our MTU", OPT_LIMITS|OPT_A2COPY, &lcp_allowoptions[0].mrru,
149       PPP_MAXMTU, PPP_MINMTU },
150     { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
151       "Disable protocol field compression",
152       OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
153     { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
154       "Disable protocol field compression",
155       OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
156     { "-p", o_bool, &lcp_wantoptions[0].passive,
157       "Set passive mode", 1 },
158     { "passive", o_bool, &lcp_wantoptions[0].passive,
159       "Set passive mode", 1 },
160     { "silent", o_bool, &lcp_wantoptions[0].silent,
161       "Set silent mode", 1 },
162     { "escape", o_special, (void *)setescape,
163       "List of character codes to escape on transmission" },
164     { "lcp-echo-failure", o_int, &lcp_echo_fails,
165       "Number of consecutive echo failures for link failure" },
166     { "lcp-echo-interval", o_int, &lcp_echo_interval,
167       "Set time in seconds between LCP echo requests" },
168     { "no-accm-test", o_int, &use_accm_test,
169       "Disable use of LCP Echo-Request asyncmap checking",
170       OPT_NOARG|OPT_VAL(0) },
171     { "small-accm-test", o_int, &use_accm_test,
172       "Use only small Echo-Requests for asyncmap checking",
173       OPT_NOARG|OPT_VAL(1) },
174     { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
175       "Set time in seconds between LCP retransmissions" },
176     { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
177       "Maximum number of LCP terminate-request transmissions" },
178     { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
179       "Maximum number of LCP configure-request transmissions" },
180     { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
181       "Set limit on number of LCP configure-naks" },
182     { "receive-all", o_bool, &lax_recv,
183       "Accept all received control characters", 1 },
184 #ifdef HAVE_MULTILINK
185     { "mrru", o_int, &lcp_wantoptions[0].mrru,
186       "Maximum received packet size for multilink bundle",
187       OPT_LIMITS, &lcp_wantoptions[0].neg_mrru, PPP_MAXMRU, PPP_MINMRU },
188     { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
189       "Use short sequence numbers in multilink headers",
190       OPT_A2COPY | 1, &lcp_allowoptions[0].neg_ssnhf },
191     { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
192       "Don't use short sequence numbers in multilink headers",
193       OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf },
194 #endif /* HAVE_MULTILINK */
195     { "endpoint", o_special, (void *)setendpoint,
196       "Endpoint discriminator for multilink", },
197     { "noendpoint", o_bool, &noendpoint,
198       "Don't send or accept multilink endpoint discriminator", 1 },
199     { "ident", o_string, identstr,
200       "LCP Identification string", OPT_STATIC, NULL, sizeof(identstr) },
201     { "noident", o_int, &noident,
202       "Disable use of LCP Identification", OPT_INC|OPT_NOARG|1 },
203 #ifdef NEGOTIATE_FCS
204     { "default-fcs", o_bool, &lcp_wantoptions[0].neg_fcs,
205       "Disable FCS Alternatives option (use default CRC-16)",
206       OPT_A2COPY, &lcp_allowoptions[0].neg_fcs },
207     { "allow-fcs", o_special, (void *)setfcsallow,
208       "Set allowable FCS types; crc16, crc32, null, or number" },
209     { "fcs", o_special, (void *)setfcswant,
210       "Set FCS type(s) desired; crc16, crc32, null, or number" },
211 #endif
212 #ifdef MUX_FRAME
213     /*
214      * if pppmux option is turned on, then the parameter to this
215      * is time value in microseconds
216      */
217     { "pppmux", o_int, &lcp_wantoptions[0].pppmux,
218       "Set PPP Multiplexing option timer", OPT_LLIMIT | OPT_A2COPY,
219 	&lcp_allowoptions[0].pppmux, 0, 0 },
220 #endif
221     {NULL}
222 };
223 
224 /* global vars */
225 fsm lcp_fsm[NUM_PPP];			/* LCP fsm structure (global)*/
226 lcp_options lcp_wantoptions[NUM_PPP];	/* Options that we want to request */
227 lcp_options lcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
228 lcp_options lcp_allowoptions[NUM_PPP];	/* Options we allow peer to request */
229 lcp_options lcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
230 u_int32_t xmit_accm[NUM_PPP][8];	/* extended transmit ACCM */
231 
232 /*
233  * These variables allow a plugin to assert limits on the maximum
234  * MRU/MTU values that can be negotiated.
235  */
236 int absmax_mru = PPP_MAXMRU;
237 int absmax_mtu = PPP_MAXMTU;
238 
239 static int lcp_echos_pending = 0;	/* Number of outstanding echo msgs */
240 static int lcp_echo_number   = 0;	/* ID number of next echo frame */
241 static int lcp_echo_timer_running = 0;  /* set if a timer is running */
242 static bool lcp_echo_accm_test = 0;	/* flag if still testing ACCM */
243 static int lcp_echo_badreplies = 0;	/* number of bad replies from peer */
244 /*
245  * The maximum number of bad replies we tolerate before bringing the
246  * link down.
247  */
248 #define LCP_ECHO_MAX_BADREPLIES	10
249 
250 /*
251  * Callbacks for fsm code.  (CI = Configuration Information)
252  */
253 static void lcp_resetci __P((fsm *));	/* Reset our CI */
254 static int  lcp_cilen __P((fsm *));		/* Return length of our CI */
255 static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */
256 static int  lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
257 static int  lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
258 static int  lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
259 static int  lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */
260 static void lcp_up __P((fsm *));		/* We're UP */
261 static void lcp_down __P((fsm *));		/* We're DOWN */
262 static void lcp_starting __P((fsm *));	/* We need lower layer up */
263 static void lcp_finished __P((fsm *));	/* We need lower layer down */
264 static int  lcp_extcode __P((fsm *, int, int, u_char *, int));
265 static void lcp_rprotrej __P((fsm *, u_char *, int));
266 static int lcp_coderej __P((fsm *f, int code, int id, u_char *inp, int len));
267 
268 /*
269  * routines to send LCP echos to peer
270  */
271 
272 static void lcp_echo_lowerup __P((int));
273 static void lcp_echo_lowerdown __P((int));
274 static void LcpEchoTimeout __P((void *));
275 static int lcp_received_echo_reply __P((fsm *, int, u_char *, int));
276 static void LcpSendEchoRequest __P((fsm *));
277 static void LcpLinkFailure __P((fsm *));
278 static void LcpEchoCheck __P((fsm *));
279 
280 /*
281  * routines to send and receive additional LCP packets described in
282  * section 1 of rfc1570.
283  */
284 static void LcpSendIdentification __P((fsm *));
285 static void lcp_received_identification __P((fsm *, int, u_char *, int));
286 static void LcpSendTimeRemaining __P((fsm *, u_int32_t));
287 static void lcp_timeremaining __P((void *));
288 static void lcp_received_timeremain __P((fsm *, int, u_char *, int));
289 
290 
291 static fsm_callbacks lcp_callbacks = {	/* LCP callback routines */
292     lcp_resetci,		/* Reset our Configuration Information */
293     lcp_cilen,			/* Length of our Configuration Information */
294     lcp_addci,			/* Add our Configuration Information */
295     lcp_ackci,			/* ACK our Configuration Information */
296     lcp_nakci,			/* NAK our Configuration Information */
297     lcp_rejci,			/* Reject our Configuration Information */
298     lcp_reqci,			/* Request peer's Configuration Information */
299     lcp_up,			/* Called when fsm reaches OPENED state */
300     lcp_down,			/* Called when fsm leaves OPENED state */
301     lcp_starting,		/* Called when we want the lower layer up */
302     lcp_finished,		/* Called when we want the lower layer down */
303     NULL,			/* Retransmission is necessary */
304     lcp_extcode,		/* Called to handle LCP-specific codes */
305     "LCP",			/* String name of protocol */
306     lcp_coderej,		/* Peer rejected a code number */
307 };
308 
309 /*
310  * Protocol entry points.
311  * Some of these are called directly.
312  */
313 
314 static void lcp_init __P((int));
315 static void lcp_input __P((int, u_char *, int));
316 static void lcp_protrej __P((int));
317 static int  lcp_printpkt __P((u_char *, int,
318     void (*) __P((void *, const char *, ...)), void *));
319 
320 
321 struct protent lcp_protent = {
322     PPP_LCP,		/* Protocol Number for LCP */
323     lcp_init,		/* Initializes LCP */
324     lcp_input,		/* Processes a received LCP packet */
325     lcp_protrej,	/* Process a received Protocol-reject */
326     lcp_lowerup,	/* Called after the serial device has been set up */
327     lcp_lowerdown,	/* Called when the link is brought down */
328     lcp_open,		/* Called after lcp_lowerup when bringing up the link */
329     lcp_close,		/* Called when the link goes down */
330     lcp_printpkt,	/* Print a packet in human readable form */
331     NULL,		/* Process a received data packet */
332     1,			/* LCP is enabled by default */
333     "LCP",		/* Name of the protocol */
334     NULL,		/* Name of the corresponding data protocol */
335     lcp_option_list,	/* List of LCP command-line options */
336     NULL,		/* Assigns default values for options */
337     NULL,		/* Configures demand-dial */
338     NULL		/* Bring up the link for this packet? */
339 };
340 
341 int lcp_loopbackfail = DEFLOOPBACKFAIL;
342 
343 /*
344  * Length of each type of configuration option (in octets)
345  */
346 #define CILEN_VOID	2
347 #define CILEN_CHAR	3
348 #define CILEN_SHORT	4	/* CILEN_VOID + 2 */
349 #define CILEN_CHAP	5	/* CILEN_VOID + 2 + 1 */
350 #define CILEN_LONG	6	/* CILEN_VOID + 4 */
351 #define CILEN_LQR	8	/* CILEN_VOID + 2 + 4 */
352 #define CILEN_CBCP	3
353 
354 
355 /*
356  * setescape - add chars to the set we escape on transmission.
357  */
358 /*ARGSUSED*/
359 static int
360 setescape(argv, opt)
361     char **argv;
362     option_t *opt;
363 {
364     int n, ret;
365     char *p, *endp;
366 
367     p = *argv;
368     ret = 1;
369     while (*p != '\0') {
370 	n = strtol(p, &endp, 16);
371 	if (p == endp) {
372 	    option_error("escape parameter contains invalid hex number '%s'",
373 			 p);
374 	    return 0;
375 	}
376 	p = endp;
377 	if (n < 0 || n == 0x5E || n > 0xFF) {
378 	    option_error("can't escape character 0x%x", n);
379 	    ret = 0;
380 	} else
381 	    xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
382 	while (*p == ',' || *p == ' ')
383 	    ++p;
384     }
385     return ret;
386 }
387 
388 /*
389  * setasyncmap - set async map negotiated
390  */
391 /*ARGSUSED*/
392 static int
393 setasyncmap(argv, opt)
394     char **argv;
395     option_t *opt;
396 {
397     u_int32_t val;
398     char *endp;
399 
400     val = strtoul(*argv, &endp, 16);
401     if (*argv == endp) {
402 	option_error("invalid numeric parameter '%s' for 'asyncmap' option",
403 	    *argv);
404 	return 0;
405     }
406     lcp_wantoptions[0].asyncmap |= val;
407     lcp_wantoptions[0].neg_asyncmap = (~lcp_wantoptions[0].asyncmap != 0);
408     do_msft_workaround = 0;
409     return 1;
410 }
411 
412 /*ARGSUSED*/
413 static int
414 setendpoint(argv, opt)
415     char **argv;
416     option_t *opt;
417 {
418     if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
419 	lcp_wantoptions[0].neg_endpoint = 1;
420 	return 1;
421     }
422     option_error("Can't parse '%s' as an endpoint discriminator", *argv);
423     return 0;
424 }
425 
426 #ifdef NEGOTIATE_FCS
427 static int
428 str_to_fcstype(opt,arg)
429     lcp_options *opt;
430     char *arg;
431 {
432     char **cpp, *cp;
433     int val, len;
434 
435     if (*arg != '\0') {
436 	val = 0;
437 	while (*arg != '\0') {
438 	    len = 0;
439 	    if (isdigit(*arg)) {
440 		len = strtol(arg, &cp, 0);
441 		if (len < 0 || len > 255 || arg == cp ||
442 		    (*cp != '\0' && *cp != ','))
443 		    break;
444 		val |= len;
445 		len = cp - arg;
446 	    } else {
447 		for (cpp = fcsalt_strings; *cpp != NULL; cpp++) {
448 		    len = strlen(*cpp);
449 		    if (strncasecmp(arg, *cpp, len) == 0 &&
450 		        (arg[len] == '\0' || arg[len] == ','))
451 			break;
452 		}
453 		if (*cpp == NULL)
454 		    break;
455 		val |= 1<<(cpp-fcsalt_strings);
456 	    }
457 	    if (arg[len] == '\0') {
458 		opt->neg_fcs = 1;
459 		opt->fcs_type = val;
460 		return (1);
461 	    }
462 	    arg += len+1;
463 	}
464     }
465     option_error("Can't parse '%s' as an FCS type", arg);
466     return (0);
467 }
468 
469 /*ARGSUSED*/
470 static int
471 setfcsallow(argv, opt)
472     char **argv;
473     option_t *opt;
474 {
475     return str_to_fcstype(&lcp_allowoptions[0], *argv);
476 }
477 
478 /*ARGSUSED*/
479 static int
480 setfcswant(argv, opt)
481     char **argv;
482     option_t *opt;
483 {
484     return str_to_fcstype(&lcp_wantoptions[0], *argv);
485 }
486 #endif
487 
488 /*
489  * lcp_init - Initialize LCP.
490  */
491 static void
492 lcp_init(unit)
493     int unit;
494 {
495     fsm *f = &lcp_fsm[unit];
496     lcp_options *wo = &lcp_wantoptions[unit];
497     lcp_options *ao = &lcp_allowoptions[unit];
498 
499     f->unit = unit;
500     f->protocol = PPP_LCP;
501     f->callbacks = &lcp_callbacks;
502 
503     fsm_init(f);
504 
505     BZERO(wo, sizeof(*wo));
506     wo->neg_mru = 1;
507     wo->mru = PPP_MRU;
508     wo->neg_asyncmap = 1;
509     wo->chap_mdtype = CHAP_DIGEST_MD5;
510     wo->neg_magicnumber = 1;
511     wo->neg_pcompression = 1;
512     wo->neg_accompression = 1;
513 
514     /*
515      * Leave allowed MRU (MTU) at zero; configuration option sets it
516      * non-zero if we should nak for something else.
517      */
518     BZERO(ao, sizeof(*ao));
519     ao->neg_mru = 1;
520     ao->neg_asyncmap = 1;
521     ao->neg_chap = 1;
522 #if defined(CHAPMS) || defined(CHAPMSV2)
523 #ifdef SOL2
524     /* Check if DES wasn't exported */
525     errno = 0;
526     setkey("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
527 	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
528     if (errno == 0)
529 #endif
530     {
531 #ifdef CHAPMS
532     ao->neg_mschap = 1;
533 #endif
534 #ifdef CHAPMSV2
535     ao->neg_mschapv2 = 1;
536 #endif
537     }
538 #endif
539     ao->chap_mdtype = CHAP_DIGEST_MD5;
540     ao->neg_upap = 1;
541     ao->neg_magicnumber = 1;
542     ao->neg_pcompression = 1;
543     ao->neg_accompression = 1;
544 #ifdef CBCP_SUPPORT
545     ao->neg_cbcp = 1;
546 #endif
547     ao->neg_endpoint = 1;
548 #ifdef NEGOTIATE_FCS
549     ao->neg_fcs = 1;
550     ao->fcs_type = FCSALT_NULL|FCSALT_16|FCSALT_32;
551 #endif
552 
553     BZERO(xmit_accm[unit], sizeof(xmit_accm[0]));
554     xmit_accm[unit][3] = 0x60000000;
555 }
556 
557 
558 /*
559  * lcp_open - LCP is allowed to come up.
560  */
561 void
562 lcp_open(unit)
563     int unit;
564 {
565     fsm *f = &lcp_fsm[unit];
566     lcp_options *wo = &lcp_wantoptions[unit];
567 
568     f->flags = 0;
569     if (wo->passive)
570 	f->flags |= OPT_PASSIVE;
571     if (wo->silent)
572 	f->flags |= OPT_SILENT;
573     fsm_open(f);
574 }
575 
576 
577 /*
578  * lcp_close - Take LCP down.
579  */
580 void
581 lcp_close(unit, reason)
582     int unit;
583     char *reason;
584 {
585     fsm *f = &lcp_fsm[unit];
586 
587     if (phase != PHASE_DEAD)
588 	new_phase(PHASE_TERMINATE);
589     if (f->state == STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT))) {
590 	/*
591 	 * This action is not strictly according to the FSM in RFC1548,
592 	 * but it does mean that the program terminates if you do a
593 	 * lcp_close() in passive/silent mode when a connection hasn't
594 	 * been established.
595 	 */
596 	f->state = CLOSED;
597 	lcp_finished(f);
598 
599     } else
600 	fsm_close(&lcp_fsm[unit], reason);
601 }
602 
603 
604 /*
605  * lcp_lowerup - The lower layer is up.
606  */
607 void
608 lcp_lowerup(unit)
609     int unit;
610 {
611     lcp_options *wo = &lcp_wantoptions[unit];
612     int mru, mtu;
613 
614     mru = PPP_MRU > absmax_mru ? absmax_mru : PPP_MRU;
615     mtu = PPP_MTU > absmax_mtu ? absmax_mtu : PPP_MTU;
616 
617     /*
618      * Don't use A/C or protocol compression on transmission,
619      * but accept A/C and protocol compressed packets
620      * if we are going to ask for A/C and protocol compression.
621      */
622     ppp_set_xaccm(unit, xmit_accm[unit]);
623     ppp_send_config(unit, mtu, 0xffffffff, 0, 0);
624     ppp_recv_config(unit, mru, (lax_recv? 0: 0xffffffff),
625 		    wo->neg_pcompression, wo->neg_accompression);
626 #ifdef NEGOTIATE_FCS
627     ppp_send_fcs(unit, FCSALT_16);
628     ppp_recv_fcs(unit, FCSALT_16);
629 #endif
630 
631     fsm_setpeermru(unit, mtu);
632     lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
633 
634     fsm_lowerup(&lcp_fsm[unit]);
635 }
636 
637 
638 /*
639  * lcp_lowerdown - The lower layer is down.
640  */
641 void
642 lcp_lowerdown(unit)
643     int unit;
644 {
645     fsm_lowerdown(&lcp_fsm[unit]);
646 }
647 
648 
649 /*
650  * lcp_input - Input LCP packet.
651  */
652 static void
653 lcp_input(unit, p, len)
654     int unit;
655     u_char *p;
656     int len;
657 {
658     fsm *f = &lcp_fsm[unit];
659 
660     fsm_input(f, p, len);
661 }
662 
663 
664 /*
665  * lcp_extcode - Handle a LCP-specific code.
666  */
667 static int
668 lcp_extcode(f, code, id, inp, len)
669     fsm *f;
670     int code, id;
671     u_char *inp;
672     int len;
673 {
674     u_char *magp;
675 
676     switch( code ){
677     case CODE_PROTREJ:
678 	lcp_rprotrej(f, inp, len);
679 	break;
680 
681     case CODE_ECHOREQ:
682 	if (f->state != OPENED)
683 	    break;
684 	magp = inp;
685 	PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
686 	fsm_sdata(f, CODE_ECHOREP, id, inp, len);
687 	break;
688 
689     case CODE_ECHOREP:
690 	if (!lcp_received_echo_reply(f, id, inp, len)) {
691 	    lcp_echo_badreplies++;
692 	    if (lcp_echo_badreplies > LCP_ECHO_MAX_BADREPLIES) {
693 		LcpLinkFailure(f);
694 		lcp_echos_pending = 0;
695 		lcp_echo_badreplies = 0;
696 	    }
697 	}
698 	break;
699 
700     case CODE_DISCREQ:
701 	break;
702 
703     case CODE_IDENT:
704 	/* More than one 'noident' tells us to reject the code number. */
705 	if (noident > 1)
706 	    return 0;
707 	lcp_received_identification(f, id, inp, len);
708 	break;
709 
710     case CODE_TIMEREMAIN:
711 	lcp_received_timeremain(f, id, inp, len);
712 	break;
713 
714     default:
715 	return 0;
716     }
717     return 1;
718 }
719 
720 /*
721  * lcp_rprotrej - Receive an Protocol-Reject.
722  *
723  * Figure out which protocol is rejected and inform it.
724  */
725 static void
726 lcp_rprotrej(f, inp, len)
727     fsm *f;
728     u_char *inp;
729     int len;
730 {
731     int i;
732     struct protent *protp;
733     u_short prot;
734 
735     if (len < 2) {
736 	dbglog("lcp_rprotrej: Rcvd short Protocol-Reject packet!");
737 	return;
738     }
739 
740     GETSHORT(prot, inp);
741 
742     /*
743      * Protocol-Reject packets received in any state other than the LCP
744      * OPENED state SHOULD be silently discarded.
745      */
746     if( f->state != OPENED ){
747 	dbglog("Protocol-Reject discarded: LCP in state %s",
748 	    fsm_state(f->state));
749 	return;
750     }
751 
752     /*
753      * Upcall the proper Protocol-Reject routine.
754      */
755     for (i = 0; (protp = protocols[i]) != NULL; ++i)
756 	if (protp->protocol == prot && protp->enabled_flag) {
757 	    (*protp->protrej)(f->unit);
758 	    return;
759 	}
760 
761     warn("Protocol-Reject for unsupported protocol 0x%x", prot);
762 }
763 
764 
765 /*
766  * lcp_protrej - A Protocol-Reject was received.
767  */
768 /*ARGSUSED*/
769 static void
770 lcp_protrej(unit)
771     int unit;
772 {
773     /*
774      * Can't reject LCP!
775      */
776     error("Received Protocol-Reject for LCP!");
777 }
778 
779 /*
780  * lcp_coderej - A Code-Reject was received.
781  */
782 /*ARGSUSED*/
783 static int
784 lcp_coderej(f, code, id, inp, len)
785 	fsm *f;
786 	int code;
787 	int id;
788 	u_char *inp;
789 	int len;
790 {
791 	/* The peer cannot reject these code numbers. */
792 	if (code >= CODE_CONFREQ && code <= CODE_PROTREJ)
793 		return 1;
794 	switch (code) {
795 	case CODE_ECHOREQ:
796 	    /*
797 	     * If the peer rejects an Echo-Request, then stop doing that.
798 	     */
799 	    if (lcp_echo_timer_running != 0) {
800 		UNTIMEOUT (LcpEchoTimeout, f);
801 		lcp_echo_timer_running = 0;
802 		lcp_echo_interval = 0;
803 	    }
804 	    break;
805 	}
806 	return 0;
807 }
808 
809 /*
810  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
811  */
812 void
813 lcp_sprotrej(unit, p, len)
814     int unit;
815     u_char *p;
816     int len;
817 {
818     /*
819      * Send back the protocol and the information field of the
820      * rejected packet.  We only get here if LCP is in the OPENED state.
821      */
822     p += 2;
823     len -= 2;
824 
825     fsm_sdata(&lcp_fsm[unit], CODE_PROTREJ, ++lcp_fsm[unit].id,
826 	      p, len);
827 }
828 
829 
830 /*
831  * lcp_resetci - Reset our CI.
832  */
833 static void
834 lcp_resetci(f)
835     fsm *f;
836 {
837     lcp_options *wo = &lcp_wantoptions[f->unit];
838     lcp_options *go = &lcp_gotoptions[f->unit];
839     lcp_options *ao = &lcp_allowoptions[f->unit];
840 
841     wo->magicnumber = magic();
842     wo->numloops = 0;
843     sentident = 0;
844     *go = *wo;
845     if (!multilink) {
846 	go->neg_mrru = 0;
847 	go->neg_ssnhf = 0;
848     }
849     if (noendpoint)
850 	ao->neg_endpoint = 0;
851     if (go->mru > absmax_mru)
852 	go->mru = absmax_mru;
853     if (ao->mru > absmax_mtu)
854 	ao->mru = absmax_mtu;
855     unsolicit_mru = 1;
856     fsm_setpeermru(f->unit, PPP_MTU > absmax_mtu ? absmax_mtu : PPP_MTU);
857     auth_reset(f->unit);
858 }
859 
860 
861 /*
862  * lcp_cilen - Return length of our CI.
863  */
864 static int
865 lcp_cilen(f)
866     fsm *f;
867 {
868     lcp_options *go = &lcp_gotoptions[f->unit];
869 
870 #define LENCIVOID(neg)	((neg) ? CILEN_VOID : 0)
871 #define LENCICHAP(neg)	((neg) ? CILEN_CHAP : 0)
872 #define LENCICHAR(neg)	((neg) ? CILEN_CHAR : 0)
873 #define LENCISHORT(neg)	((neg) ? CILEN_SHORT : 0)
874 #define LENCILONG(neg)	((neg) ? CILEN_LONG : 0)
875 #define LENCILQR(neg)	((neg) ? CILEN_LQR: 0)
876 #define LENCICBCP(neg)	((neg) ? CILEN_CBCP: 0)
877     /*
878      * NB: we only ask for one of CHAP and UPAP, even if we will
879      * accept either.
880      */
881     return (LENCISHORT(go->neg_mru && go->mru != PPP_MRU) +
882 	    LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
883 	    LENCICHAP(go->neg_chap || go->neg_mschap || go->neg_mschapv2) +
884 	    LENCISHORT(!go->neg_chap && go->neg_upap && !go->neg_mschap &&
885 		!go->neg_mschapv2) +
886 	    LENCILQR(go->neg_lqr) +
887 	    LENCICBCP(go->neg_cbcp) +
888 	    LENCILONG(go->neg_magicnumber) +
889 	    LENCIVOID(go->neg_pcompression) +
890 	    LENCIVOID(go->neg_accompression) +
891 	    LENCICHAR(go->neg_fcs) +
892 	    LENCISHORT(go->neg_mrru) +
893 	    LENCIVOID(go->neg_ssnhf) +
894 #ifdef MUX_FRAME
895             LENCIVOID(go->pppmux) +
896 #endif
897 	    (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
898 }
899 
900 
901 /*
902  * lcp_addci - Add our desired CIs to a packet.
903  */
904 static void
905 lcp_addci(f, ucp, lenp)
906     fsm *f;
907     u_char *ucp;
908     int *lenp;
909 {
910     lcp_options *go = &lcp_gotoptions[f->unit];
911     lcp_options *ho = &lcp_hisoptions[f->unit];
912     u_char *start_ucp = ucp;
913 
914 #define ADDCIVOID(opt, neg) \
915     if (neg) { \
916 	PUTCHAR(opt, ucp); \
917 	PUTCHAR(CILEN_VOID, ucp); \
918     }
919 #define ADDCISHORT(opt, neg, val) \
920     if (neg) { \
921 	PUTCHAR(opt, ucp); \
922 	PUTCHAR(CILEN_SHORT, ucp); \
923 	PUTSHORT(val, ucp); \
924     }
925 #define ADDCICHAP(opt, neg, val, digest) \
926     if (neg) { \
927 	PUTCHAR(opt, ucp); \
928 	PUTCHAR(CILEN_CHAP, ucp); \
929 	PUTSHORT(val, ucp); \
930 	PUTCHAR(digest, ucp); \
931     }
932 #define ADDCILONG(opt, neg, val) \
933     if (neg) { \
934 	PUTCHAR(opt, ucp); \
935 	PUTCHAR(CILEN_LONG, ucp); \
936 	PUTLONG(val, ucp); \
937     }
938 #define ADDCILQR(opt, neg, val) \
939     if (neg) { \
940 	PUTCHAR(opt, ucp); \
941 	PUTCHAR(CILEN_LQR, ucp); \
942 	PUTSHORT(PPP_LQR, ucp); \
943 	PUTLONG(val, ucp); \
944     }
945 #define ADDCICHAR(opt, neg, val) \
946     if (neg) { \
947 	PUTCHAR(opt, ucp); \
948 	PUTCHAR(CILEN_CHAR, ucp); \
949 	PUTCHAR(val, ucp); \
950     }
951 #define ADDCIENDP(opt, neg, class, val, len) \
952     if (neg) { \
953 	int i; \
954 	PUTCHAR(opt, ucp); \
955 	PUTCHAR(CILEN_CHAR + len, ucp); \
956 	PUTCHAR(class, ucp); \
957 	for (i = 0; i < len; ++i) \
958 	    PUTCHAR(val[i], ucp); \
959     }
960 
961     ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_MRU, go->mru);
962     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
963 	      go->asyncmap);
964     /* go->chap_mdtype always points to a useful value */
965     ADDCICHAP(CI_AUTHTYPE, go->neg_chap || go->neg_mschap || go->neg_mschapv2,
966 	PPP_CHAP, go->chap_mdtype);
967     ADDCISHORT(CI_AUTHTYPE, !(go->neg_chap || go->neg_mschap ||
968 	go->neg_mschapv2) && go->neg_upap, PPP_PAP);
969     /* We can't both say zero for LQR period. */
970     if (f->state == ACKSENT && go->neg_lqr && go->lqr_period == 0 &&
971 	ho->neg_lqr && ho->lqr_period == 0)
972 	go->lqr_period = 500;
973     ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
974     ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBOP_CBCP);
975     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
976     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
977     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
978     ADDCICHAR(CI_FCSALTERN, (go->neg_fcs && go->fcs_type != 0), go->fcs_type);
979     ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
980 	      go->endpoint.value, go->endpoint.length);
981 #ifdef MUX_FRAME
982     ADDCIVOID(CI_MUXING, go->pppmux);
983 #endif
984     ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
985     ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
986 
987     if (ucp - start_ucp != *lenp) {
988 	/* this should never happen, because peer_mtu should be 1500 */
989 	error("Bug in lcp_addci: wrong length");
990     }
991 }
992 
993 
994 /*
995  * lcp_ackci - Ack our CIs.
996  * This should not modify any state if the Ack is bad.
997  *
998  * Returns:
999  *	0 - Ack was bad.
1000  *	1 - Ack was good.
1001  */
1002 static int
1003 lcp_ackci(f, p, len)
1004     fsm *f;
1005     u_char *p;
1006     int len;
1007 {
1008     lcp_options *go = &lcp_gotoptions[f->unit];
1009 #ifdef MUX_FRAME
1010     lcp_options *ao = &lcp_allowoptions[f->unit];
1011 #endif
1012     u_char cilen, citype, cichar;
1013     u_short cishort;
1014     u_int32_t cilong;
1015 
1016     /*
1017      * CIs must be in exactly the same order that we sent.
1018      * Check packet length and CI length at each step.
1019      * If we find any deviations, then this packet is bad.
1020      */
1021 #define ACKCIVOID(opt, neg) \
1022     if (neg) { \
1023 	if ((len -= CILEN_VOID) < 0) \
1024 	    goto bad; \
1025 	GETCHAR(citype, p); \
1026 	GETCHAR(cilen, p); \
1027 	if (cilen != CILEN_VOID || \
1028 	    citype != opt) \
1029 	    goto bad; \
1030     }
1031 #define ACKCISHORT(opt, neg, val) \
1032     if (neg) { \
1033 	if ((len -= CILEN_SHORT) < 0) \
1034 	    goto bad; \
1035 	GETCHAR(citype, p); \
1036 	GETCHAR(cilen, p); \
1037 	if (cilen != CILEN_SHORT || \
1038 	    citype != opt) \
1039 	    goto bad; \
1040 	GETSHORT(cishort, p); \
1041 	if (cishort != val) \
1042 	    goto bad; \
1043     }
1044 #define ACKCIAUTH(opt, neg, val) \
1045     if (neg) { \
1046 	if ((len -= CILEN_SHORT) < 0) \
1047 	    goto bad; \
1048 	GETCHAR(citype, p); \
1049 	GETCHAR(cilen, p); \
1050 	if (cilen != CILEN_SHORT || \
1051 	    citype != opt) \
1052 	    goto bad; \
1053 	GETSHORT(cishort, p); \
1054 	if (cishort != val) \
1055 	    goto bad; \
1056 	peer_nak_auth = 0; \
1057 	peer_reject_auth = 0; \
1058     }
1059 #define ACKCICHAR(opt, neg, val) \
1060     if (neg) { \
1061 	if ((len -= CILEN_CHAR) < 0) \
1062 	    goto bad; \
1063 	GETCHAR(citype, p); \
1064 	GETCHAR(cilen, p); \
1065 	if (cilen != CILEN_CHAR || \
1066 	    citype != opt) \
1067 	    goto bad; \
1068 	GETCHAR(cichar, p); \
1069 	if (cichar != val) \
1070 	    goto bad; \
1071     }
1072 #define ACKCICHAP(opt, neg, val, digest) \
1073     if (neg) { \
1074 	if ((len -= CILEN_CHAP) < 0) \
1075 	    goto bad; \
1076 	GETCHAR(citype, p); \
1077 	GETCHAR(cilen, p); \
1078 	if (cilen != CILEN_CHAP || \
1079 	    citype != opt) \
1080 	    goto bad; \
1081 	GETSHORT(cishort, p); \
1082 	if (cishort != val) \
1083 	    goto bad; \
1084 	GETCHAR(cichar, p); \
1085 	if (cichar != digest) \
1086 	  goto bad; \
1087 	peer_nak_auth = 0; \
1088 	peer_reject_auth = 0; \
1089     }
1090 #define ACKCILONG(opt, neg, val) \
1091     if (neg) { \
1092 	if ((len -= CILEN_LONG) < 0) \
1093 	    goto bad; \
1094 	GETCHAR(citype, p); \
1095 	GETCHAR(cilen, p); \
1096 	if (cilen != CILEN_LONG || \
1097 	    citype != opt) \
1098 	    goto bad; \
1099 	GETLONG(cilong, p); \
1100 	if (cilong != val) \
1101 	    goto bad; \
1102     }
1103 #define ACKCILQR(opt, neg, val) \
1104     if (neg) { \
1105 	if ((len -= CILEN_LQR) < 0) \
1106 	    goto bad; \
1107 	GETCHAR(citype, p); \
1108 	GETCHAR(cilen, p); \
1109 	if (cilen != CILEN_LQR || \
1110 	    citype != opt) \
1111 	    goto bad; \
1112 	GETSHORT(cishort, p); \
1113 	if (cishort != PPP_LQR) \
1114 	    goto bad; \
1115 	GETLONG(cilong, p); \
1116 	if (cilong != val) \
1117 	  goto bad; \
1118     }
1119 #define ACKCIENDP(opt, neg, class, val, vlen) \
1120     if (neg) { \
1121 	int i; \
1122 	if ((len -= CILEN_CHAR + vlen) < 0) \
1123 	    goto bad; \
1124 	GETCHAR(citype, p); \
1125 	GETCHAR(cilen, p); \
1126 	if (cilen != CILEN_CHAR + vlen || \
1127 	    citype != opt) \
1128 	    goto bad; \
1129 	GETCHAR(cichar, p); \
1130 	if (cichar != class) \
1131 	    goto bad; \
1132 	for (i = 0; i < vlen; ++i) { \
1133 	    GETCHAR(cichar, p); \
1134 	    if (cichar != val[i]) \
1135 		goto bad; \
1136 	} \
1137     }
1138 
1139     ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_MRU, go->mru);
1140     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
1141 	      go->asyncmap);
1142     /* go->chap_mdtype always points to a useful value */
1143     ACKCICHAP(CI_AUTHTYPE, go->neg_chap || go->neg_mschap || go->neg_mschapv2,
1144 	PPP_CHAP, go->chap_mdtype);
1145     ACKCIAUTH(CI_AUTHTYPE, !(go->neg_chap || go->neg_mschap ||
1146 	go->neg_mschapv2) && go->neg_upap, PPP_PAP);
1147     ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1148     ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBOP_CBCP);
1149     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
1150     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
1151     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
1152     ACKCICHAR(CI_FCSALTERN, go->neg_fcs, go->fcs_type);
1153     ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
1154 	      go->endpoint.value, go->endpoint.length);
1155 #ifdef MUX_FRAME
1156     ACKCIVOID(CI_MUXING, go->pppmux);
1157     if (go->pppmux)
1158     	go->pppmux = ao->pppmux;
1159 #endif
1160     ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
1161     ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
1162 
1163     /*
1164      * If there are any remaining CIs, then this packet is bad.
1165      */
1166     if (len != 0)
1167 	goto bad;
1168     return (1);
1169 bad:
1170     dbglog("lcp_acki: received bad Ack!");
1171     return (0);
1172 }
1173 
1174 
1175 /*
1176  * lcp_nakci - Peer has sent a NAK for some of our CIs.
1177  * This should not modify any state if the Nak is bad
1178  * or if LCP is in the OPENED state.
1179  *
1180  * Returns:
1181  *	0 - Nak was bad.
1182  *	1 - Nak was good.
1183  */
1184 static int
1185 lcp_nakci(f, p, len)
1186     fsm *f;
1187     u_char *p;
1188     int len;
1189 {
1190     lcp_options *go = &lcp_gotoptions[f->unit];
1191     lcp_options *wo = &lcp_wantoptions[f->unit];
1192     u_char citype, cichar, *next;
1193     u_short cishort;
1194     u_int32_t cilong;
1195     lcp_options no;		/* options we've seen Naks for */
1196     lcp_options try;		/* options to request next time */
1197     int looped_back = 0;
1198     int cilen;
1199 
1200     BZERO(&no, sizeof(no));
1201     try = *go;
1202 
1203     /*
1204      * Any Nak'd CIs must be in exactly the same order that we sent.
1205      * Check packet length and CI length at each step.
1206      * If we find any deviations, then this packet is bad.
1207      */
1208 #define NAKCIVOID(opt, neg) \
1209     if (go->neg && \
1210 	len >= CILEN_VOID && \
1211 	p[1] == CILEN_VOID && \
1212 	p[0] == opt) { \
1213 	len -= CILEN_VOID; \
1214 	INCPTR(CILEN_VOID, p); \
1215 	no.neg = 1; \
1216 	try.neg = 0; \
1217     }
1218 #define NAKCICHAR(opt, neg, code) \
1219     if (go->neg && \
1220 	len >= CILEN_CHAR && \
1221 	p[1] == CILEN_CHAR && \
1222 	p[0] == opt) { \
1223 	len -= CILEN_CHAR; \
1224 	INCPTR(2, p); \
1225 	GETCHAR(cichar, p); \
1226 	no.neg = 1; \
1227 	code \
1228     }
1229 #define NAKCISHORT(opt, neg, code) \
1230     if (go->neg && \
1231 	len >= CILEN_SHORT && \
1232 	p[1] == CILEN_SHORT && \
1233 	p[0] == opt) { \
1234 	len -= CILEN_SHORT; \
1235 	INCPTR(2, p); \
1236 	GETSHORT(cishort, p); \
1237 	no.neg = 1; \
1238 	code \
1239     }
1240 #define NAKCILONG(opt, neg, code) \
1241     if (go->neg && \
1242 	len >= CILEN_LONG && \
1243 	p[1] == CILEN_LONG && \
1244 	p[0] == opt) { \
1245 	len -= CILEN_LONG; \
1246 	INCPTR(2, p); \
1247 	GETLONG(cilong, p); \
1248 	no.neg = 1; \
1249 	code \
1250     }
1251 #define NAKCILQR(opt, neg, code) \
1252     if (go->neg && \
1253 	len >= CILEN_LQR && \
1254 	p[1] == CILEN_LQR && \
1255 	p[0] == opt) { \
1256 	len -= CILEN_LQR; \
1257 	INCPTR(2, p); \
1258 	GETSHORT(cishort, p); \
1259 	GETLONG(cilong, p); \
1260 	no.neg = 1; \
1261 	code \
1262     }
1263 #define NAKCIENDP(opt, neg) \
1264     if (go->neg && \
1265 	len >= CILEN_CHAR && \
1266 	p[0] == opt && \
1267 	p[1] >= CILEN_CHAR && \
1268 	p[1] <= len) { \
1269 	len -= p[1]; \
1270 	INCPTR(p[1], p); \
1271 	no.neg = 1; \
1272 	try.neg = 0; \
1273     }
1274 
1275     /*
1276      * We don't care if they want to send us smaller packets than
1277      * we want.  Therefore, accept any MRU less than what we asked for,
1278      * but then ignore the new value when setting the MRU in the kernel.
1279      * If they send us a bigger MRU than what we asked, accept it, up to
1280      * the limit of the default MRU we'd get if we didn't negotiate.
1281      */
1282     if (go->neg_mru && go->mru != PPP_MRU) {
1283 	NAKCISHORT(CI_MRU, neg_mru,
1284 		   if (cishort <= wo->mru ||
1285 		       (cishort <= PPP_MRU && cishort <= absmax_mru))
1286 		       try.mru = cishort;
1287 		   );
1288     }
1289 
1290     /*
1291      * Add any characters they want to our (receive-side) asyncmap.
1292      */
1293     if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
1294 	NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
1295 		  try.asyncmap = go->asyncmap | cilong;
1296 		  );
1297     }
1298 
1299     /*
1300      * If they've nak'd our authentication-protocol, check whether
1301      * they are proposing a different protocol, or a different
1302      * hash algorithm for CHAP.
1303      */
1304     if ((go->neg_chap || go->neg_mschap || go->neg_mschapv2 || go->neg_upap) &&
1305 	len >= CILEN_SHORT && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT &&
1306 	p[1] <= len) {
1307 	cilen = p[1];
1308 	len -= cilen;
1309 	INCPTR(2, p);
1310         GETSHORT(cishort, p);
1311 	peer_nak_auth = 1;
1312 	nak_auth_orig = (go->neg_chap || go->neg_mschap || go->neg_mschapv2) ?
1313 	    PPP_CHAP : PPP_PAP;
1314 	nak_auth_proto = cishort;
1315 	if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
1316 	    no.neg_upap = go->neg_upap;
1317 	    /*
1318 	     * If we were asking for CHAP, they obviously don't want to do it.
1319 	     * If we weren't asking for CHAP, then we were asking for PAP,
1320 	     * in which case this Nak is bad.
1321 	     */
1322 	    if (!go->neg_chap && !go->neg_mschap && !go->neg_mschapv2)
1323 		goto bad;
1324 	    try.neg_chap = 0;
1325 	    try.neg_mschap = 0;
1326 	    try.neg_mschapv2 = 0;
1327 
1328 	} else if (cishort == PPP_CHAP && cilen >= CILEN_CHAP) {
1329 	    /* stop asking for that type */
1330 	    switch (go->chap_mdtype) {
1331 	    case CHAP_DIGEST_MD5:
1332 		no.neg_chap = go->neg_chap;
1333 		try.neg_chap = 0;
1334 		break;
1335 	    case CHAP_MICROSOFT:
1336 		no.neg_mschap = go->neg_mschap;
1337 		try.neg_mschap = 0;
1338 		break;
1339 	    case CHAP_MICROSOFT_V2:
1340 		no.neg_mschapv2 = go->neg_mschapv2;
1341 		try.neg_mschapv2 = 0;
1342 		break;
1343 	    }
1344 	    GETCHAR(cichar, p);
1345 	    /* Allow >= on length here for broken and silly peers. */
1346 	    p += cilen - CILEN_CHAP;
1347 	    try.neg_upap = 0;
1348 	    if ((cichar == CHAP_DIGEST_MD5 && wo->neg_chap) ||
1349 		(cichar == CHAP_MICROSOFT && wo->neg_mschap) ||
1350 		(cichar == CHAP_MICROSOFT_V2 && wo->neg_mschapv2)) {
1351 		/* Try its requested algorithm. */
1352 		try.chap_mdtype = cichar;
1353 	    } else {
1354 		goto try_another;
1355 	    }
1356 
1357 	} else {
1358 	    /*
1359 	     * We don't recognize what they're suggesting.
1360 	     * Stop asking for what we were asking for.
1361 	     */
1362 	try_another:
1363 	    if (go->neg_chap || go->neg_mschap || go->neg_mschapv2) {
1364 		switch (go->chap_mdtype) {
1365 		case CHAP_DIGEST_MD5:
1366 		    try.neg_chap = 0;
1367 		    if (wo->neg_mschap) {
1368 			try.chap_mdtype = CHAP_MICROSOFT;
1369 			break;
1370 		    }
1371 			/*FALLTHROUGH*/
1372 		case CHAP_MICROSOFT:
1373 		    try.neg_mschap = 0;
1374 		    if (wo->neg_mschapv2) {
1375 			try.chap_mdtype = CHAP_MICROSOFT_V2;
1376 			break;
1377 		    }
1378 			/*FALLTHROUGH*/
1379 		case CHAP_MICROSOFT_V2:
1380 		    try.neg_mschapv2 = 0;
1381 		    break;
1382 		}
1383 	    } else
1384 		try.neg_upap = 0;
1385 	    p += cilen - CILEN_SHORT;
1386 	}
1387     }
1388 
1389     /*
1390      * If they can't cope with our link quality protocol, we'll have
1391      * to stop asking for LQR.  We haven't got any other protocol.  If
1392      * they Nak the reporting period, then the following logic
1393      * applies:
1394      * If it suggests zero and go->neg_fcs is true and
1395      * ao->lqr_period isn't zero, then take its suggestion.  If it
1396      * suggests zero otherwise, ignore it.  If it suggests a nonzero
1397      * value and wo->lqr_period is zero, then take its suggestion.  If
1398      * it suggests a nonzero value otherwise that's less than
1399      * wo->lqr_period, then ignore it.
1400      */
1401     NAKCILQR(CI_QUALITY, neg_lqr,
1402 	     if (cishort != PPP_LQR)
1403 		 try.neg_lqr = 0;
1404 	     else if (cilong == 0 && go->neg_fcs && wo->lqr_period != 0)
1405 		 try.lqr_period = cilong;
1406 	     else if (cilong != 0 &&
1407 		 (wo->lqr_period == 0 || cilong > wo->lqr_period))
1408 		 try.lqr_period = cilong;
1409 	     );
1410 
1411     /*
1412      * Only implementing CBCP...not the rest of the callback options
1413      */
1414     NAKCICHAR(CI_CALLBACK, neg_cbcp,
1415               try.neg_cbcp = 0;
1416               );
1417 
1418     /*
1419      * Check for a looped-back line.
1420      */
1421     NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1422 	      try.magicnumber = magic();
1423 	      looped_back = 1;
1424 	      );
1425 
1426     /*
1427      * Peer shouldn't send Nak for protocol compression or
1428      * address/control compression requests; they should send
1429      * a Reject instead.  If they send a Nak, treat it as a Reject.
1430      */
1431     NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1432     NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1433 
1434     /*
1435      * Remove any FCS types it doesn't like from our (receive-side)
1436      * FCS list.
1437      */
1438     NAKCICHAR(CI_FCSALTERN, neg_fcs, try.fcs_type = go->fcs_type & cichar;);
1439 
1440 #ifdef MUX_FRAME
1441     /* Nacked MUX option */
1442     NAKCIVOID(CI_MUXING, pppmux);
1443 #endif
1444 
1445     /*
1446      * Nak of the endpoint discriminator option is not permitted,
1447      * treat it like a reject.
1448      */
1449     NAKCIENDP(CI_EPDISC, neg_endpoint);
1450 
1451     /*
1452      * Nak for MRRU option - accept their value if it is smaller
1453      * than the one we want.
1454      */
1455     if (go->neg_mrru) {
1456 	NAKCISHORT(CI_MRRU, neg_mrru,
1457 		   if (cishort <= wo->mrru)
1458 		       try.mrru = cishort;
1459 		   );
1460     }
1461 
1462     /*
1463      * Nak for short sequence numbers shouldn't be sent, treat it
1464      * like a reject.
1465      */
1466     NAKCIVOID(CI_SSNHF, neg_ssnhf);
1467 
1468     /*
1469      * There may be remaining CIs, if the peer is requesting negotiation
1470      * on an option that we didn't include in our request packet.
1471      * If we see an option that we requested, or one we've already seen
1472      * in this packet, then this packet is bad.
1473      * If we wanted to respond by starting to negotiate on the requested
1474      * option(s), we could, but we don't, because except for the
1475      * authentication type and quality protocol, if we are not negotiating
1476      * an option, it is because we were told not to.
1477      * For the authentication type, the Nak from the peer means
1478      * `let me authenticate myself with you' which is a bit pointless.
1479      * For the quality protocol, the Nak means `ask me to send you quality
1480      * reports', but if we didn't ask for them, we don't want them.
1481      * An option we don't recognize represents the peer asking to
1482      * negotiate some option we don't support, so ignore it.
1483      */
1484     while (len > CILEN_VOID) {
1485 	GETCHAR(citype, p);
1486 	GETCHAR(cilen, p);
1487 	if (cilen < CILEN_VOID || (len -= cilen) < 0)
1488 	    goto bad;
1489 	next = p + cilen - 2;
1490 
1491 	switch (citype) {
1492 	case CI_MRU:
1493 	    if ((go->neg_mru && go->mru != PPP_MRU)
1494 		|| no.neg_mru || cilen != CILEN_SHORT)
1495 		goto bad;
1496 	    GETSHORT(cishort, p);
1497 	    if (cishort < PPP_MRU && cishort < absmax_mru) {
1498 		try.neg_mru = 1;
1499 		try.mru = cishort;
1500 		notice("Peer sent unsolicited Nak for MRU less than default.");
1501 	    }
1502 	    break;
1503 	case CI_ASYNCMAP:
1504 	    if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1505 		|| no.neg_asyncmap || cilen != CILEN_LONG)
1506 		goto bad;
1507 	    break;
1508 	case CI_AUTHTYPE:
1509 	    unsolicited_nak_auth = 1;
1510 	    if (cilen >= CILEN_SHORT) {
1511 		GETSHORT(unsolicit_auth_proto, p);
1512 	    } else {
1513 		unsolicit_auth_proto = 0;
1514 	    }
1515 	    if (go->neg_chap || no.neg_chap ||
1516 		go->neg_mschap || no.neg_mschap ||
1517 		go->neg_mschapv2 || no.neg_mschapv2 ||
1518 		go->neg_upap || no.neg_upap)
1519 		goto bad;
1520 	    break;
1521 	case CI_MAGICNUMBER:
1522 	    if (go->neg_magicnumber || no.neg_magicnumber ||
1523 		cilen != CILEN_LONG)
1524 		goto bad;
1525 	    break;
1526 	case CI_PCOMPRESSION:
1527 	    if (go->neg_pcompression || no.neg_pcompression
1528 		|| cilen != CILEN_VOID)
1529 		goto bad;
1530 	    break;
1531 	case CI_ACCOMPRESSION:
1532 	    if (go->neg_accompression || no.neg_accompression
1533 		|| cilen != CILEN_VOID)
1534 		goto bad;
1535 	    break;
1536 	case CI_QUALITY:
1537 	    if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1538 		goto bad;
1539 	    break;
1540 	case CI_MRRU:
1541 	    if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1542 		goto bad;
1543 	    break;
1544 	case CI_SSNHF:
1545 	    if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1546 		goto bad;
1547 	    try.neg_ssnhf = 1;
1548 	    break;
1549 	case CI_EPDISC:
1550 	    if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1551 		goto bad;
1552 	    break;
1553 	case CI_FCSALTERN:
1554 	    if (go->neg_fcs || no.neg_fcs || cilen < CILEN_CHAR)
1555 		goto bad;
1556 	    break;
1557 #ifdef MUX_FRAME
1558         case CI_MUXING:
1559             if (go->pppmux || no.pppmux || cilen < CILEN_VOID)
1560                 goto bad;
1561             break;
1562 #endif
1563 	}
1564 	p = next;
1565     }
1566 
1567     /*
1568      * OK, the Nak is good.  Now we can update state.
1569      * If there are any options left we ignore them.
1570      */
1571     if (f->state != OPENED) {
1572 	/*
1573 	 * Note:  the code once reset try.numloops to zero here if
1574 	 * looped_back wasn't set.  This is wrong because a mixture of
1575 	 * looped-back and peer data (possible if half-duplex is used)
1576 	 * will allow the link to come up, and it shouldn't.
1577 	 */
1578 	if (looped_back) {
1579 	    if (++try.numloops >= lcp_loopbackfail) {
1580 		notice("Serial line is looped back.");
1581 		lcp_close(f->unit, "Loopback detected");
1582 		status = EXIT_LOOPBACK;
1583 	    }
1584 	}
1585 	*go = try;
1586     }
1587 
1588     return 1;
1589 
1590 bad:
1591     dbglog("lcp_nakci: received bad Nak!");
1592     return 0;
1593 }
1594 
1595 
1596 /*
1597  * lcp_rejci - Peer has Rejected some of our CIs.
1598  * This should not modify any state if the Reject is bad
1599  * or if LCP is in the OPENED state.
1600  *
1601  * Returns:
1602  *	0 - Reject was bad.
1603  *	1 - Reject was good.
1604  */
1605 static int
1606 lcp_rejci(f, p, len)
1607     fsm *f;
1608     u_char *p;
1609     int len;
1610 {
1611     lcp_options *go = &lcp_gotoptions[f->unit];
1612     u_char cichar;
1613     u_short cishort;
1614     u_int32_t cilong;
1615     lcp_options try;		/* options to request next time */
1616 
1617     try = *go;
1618 
1619     /*
1620      * Any Rejected CIs must be in exactly the same order that we sent.
1621      * Check packet length and CI length at each step.
1622      * If we find any deviations, then this packet is bad.
1623      */
1624 #define REJCIVOID(opt, neg) \
1625     if (go->neg && \
1626 	len >= CILEN_VOID && \
1627 	p[1] == CILEN_VOID && \
1628 	p[0] == opt) { \
1629 	len -= CILEN_VOID; \
1630 	INCPTR(CILEN_VOID, p); \
1631 	try.neg = 0; \
1632     }
1633 #define REJCICHAR(opt, neg, val) \
1634     if (go->neg && \
1635 	len >= CILEN_CHAR && \
1636 	p[1] == CILEN_CHAR && \
1637 	p[0] == opt) { \
1638 	len -= CILEN_CHAR; \
1639 	INCPTR(2, p); \
1640 	GETCHAR(cichar, p); \
1641 	/* Check rejected value. */ \
1642 	if (cichar != val) \
1643 	    goto bad; \
1644 	try.neg = 0; \
1645     }
1646 #define REJCISHORT(opt, neg, val) \
1647     if (go->neg && \
1648 	len >= CILEN_SHORT && \
1649 	p[1] == CILEN_SHORT && \
1650 	p[0] == opt) { \
1651 	len -= CILEN_SHORT; \
1652 	INCPTR(2, p); \
1653 	GETSHORT(cishort, p); \
1654 	/* Check rejected value. */ \
1655 	if (cishort != val) \
1656 	    goto bad; \
1657 	try.neg = 0; \
1658     }
1659 #define REJCIAUTH(opt, neg, val) \
1660     if (go->neg && \
1661 	len >= CILEN_SHORT && \
1662 	p[1] == CILEN_SHORT && \
1663 	p[0] == opt) { \
1664 	len -= CILEN_SHORT; \
1665 	INCPTR(2, p); \
1666 	GETSHORT(cishort, p); \
1667 	/* Check rejected value. */ \
1668 	peer_reject_auth = 1; \
1669 	reject_auth_proto = cishort; \
1670 	if (cishort != val) \
1671 	    goto bad; \
1672 	try.neg = 0; \
1673     }
1674 #define REJCILONG(opt, neg, val) \
1675     if (go->neg && \
1676 	len >= CILEN_LONG && \
1677 	p[1] == CILEN_LONG && \
1678 	p[0] == opt) { \
1679 	len -= CILEN_LONG; \
1680 	INCPTR(2, p); \
1681 	GETLONG(cilong, p); \
1682 	/* Check rejected value. */ \
1683 	if (cilong != val) \
1684 	    goto bad; \
1685 	try.neg = 0; \
1686     }
1687 #define REJCILQR(opt, neg, val) \
1688     if (go->neg && \
1689 	len >= CILEN_LQR && \
1690 	p[1] == CILEN_LQR && \
1691 	p[0] == opt) { \
1692 	len -= CILEN_LQR; \
1693 	INCPTR(2, p); \
1694 	GETSHORT(cishort, p); \
1695 	GETLONG(cilong, p); \
1696 	/* Check rejected value. */ \
1697 	if (cishort != PPP_LQR || cilong != val) \
1698 	    goto bad; \
1699 	try.neg = 0; \
1700     }
1701 #define REJCICBCP(opt, neg, val) \
1702     if (go->neg && \
1703 	len >= CILEN_CBCP && \
1704 	p[1] == CILEN_CBCP && \
1705 	p[0] == opt) { \
1706 	len -= CILEN_CBCP; \
1707 	INCPTR(2, p); \
1708 	GETCHAR(cichar, p); \
1709 	/* Check rejected value. */ \
1710 	if (cichar != val) \
1711 	    goto bad; \
1712 	try.neg = 0; \
1713     }
1714 #define REJCIENDP(opt, neg, class, val, vlen) \
1715     if (go->neg && \
1716 	len >= CILEN_CHAR + vlen && \
1717 	p[0] == opt && \
1718 	p[1] == CILEN_CHAR + vlen) { \
1719 	int i; \
1720 	len -= CILEN_CHAR + vlen; \
1721 	INCPTR(2, p); \
1722 	GETCHAR(cichar, p); \
1723 	if (cichar != class) \
1724 	    goto bad; \
1725 	for (i = 0; i < vlen; ++i) { \
1726 	    GETCHAR(cichar, p); \
1727 	    if (cichar != val[i]) \
1728 		goto bad; \
1729 	} \
1730 	try.neg = 0; \
1731     }
1732 
1733     /* Received a Configure-Reject, try to send Identification now. */
1734     if (!noident && sentident < 3) {
1735 	LcpSendIdentification(f);
1736 	sentident++;
1737     }
1738 
1739     REJCISHORT(CI_MRU, neg_mru, go->mru);
1740     REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1741 
1742     /*
1743      * There are broken peers (such as unbundled Solaris PPP) that
1744      * send Configure-Reject for authentication when they really
1745      * intend Configure-Nak.  This code works around this problem.
1746      */
1747     if ((go->neg_chap || go->neg_mschap || go->neg_mschapv2) &&
1748 	len >= CILEN_CHAP && p[1] == CILEN_CHAP && p[0] == CI_AUTHTYPE) {
1749 	len -= CILEN_CHAP;
1750 	INCPTR(2, p);
1751 	GETSHORT(cishort, p);
1752 	GETCHAR(cichar, p);
1753 	peer_reject_auth = 1;
1754 	reject_auth_proto = cishort;
1755 	/* Check rejected value. */
1756 	if (cishort != PPP_CHAP || cichar != go->chap_mdtype)
1757 	    goto bad;
1758 	/* Disable the one that it rejected */
1759 	switch (cichar) {
1760 	case CHAP_DIGEST_MD5:
1761 	    try.neg_chap = 0;
1762 	    break;
1763 	case CHAP_MICROSOFT:
1764 	    try.neg_mschap = 0;
1765 	    break;
1766 	case CHAP_MICROSOFT_V2:
1767 	    try.neg_mschapv2 = 0;
1768 	    break;
1769 	}
1770 	/* Try another, if we can. */
1771 	if (try.neg_chap)
1772 	    try.chap_mdtype = CHAP_DIGEST_MD5;
1773 	else if (try.neg_mschap)
1774 	    try.chap_mdtype = CHAP_MICROSOFT;
1775 	else
1776 	    try.chap_mdtype = CHAP_MICROSOFT_V2;
1777     }
1778 
1779     if (!go->neg_chap && !go->neg_mschap && !go->neg_mschapv2) {
1780 	REJCIAUTH(CI_AUTHTYPE, neg_upap, PPP_PAP);
1781     }
1782     REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1783     REJCICBCP(CI_CALLBACK, neg_cbcp, CBOP_CBCP);
1784     REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1785     REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1786     REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1787     REJCICHAR(CI_FCSALTERN, neg_fcs, go->fcs_type);
1788 #ifdef MUX_FRAME
1789     REJCIVOID(CI_MUXING,pppmux);
1790 #endif
1791     REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class,
1792 	      go->endpoint.value, go->endpoint.length);
1793     REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1794     REJCIVOID(CI_SSNHF, neg_ssnhf);
1795 
1796     /*
1797      * If there are any remaining CIs, then this packet is bad.
1798      */
1799     if (len != 0)
1800 	goto bad;
1801     /*
1802      * Now we can update state.
1803      */
1804     if (f->state != OPENED)
1805 	*go = try;
1806     return 1;
1807 
1808 bad:
1809     dbglog("lcp_rejci: received bad Reject!");
1810     return 0;
1811 }
1812 
1813 
1814 /*
1815  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1816  *
1817  * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input
1818  * packet modified appropriately.  If reject_if_disagree is non-zero,
1819  * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't
1820  * return CODE_CONFACK.
1821  */
1822 static int
1823 lcp_reqci(f, p, lenp, dont_nak)
1824     fsm *f;
1825     u_char *p;		/* Requested CIs */
1826     int *lenp;		/* Length of requested CIs */
1827     int dont_nak;
1828 {
1829     lcp_options *wo = &lcp_wantoptions[f->unit];
1830     lcp_options *go = &lcp_gotoptions[f->unit];
1831     lcp_options *ho = &lcp_hisoptions[f->unit];
1832     lcp_options *ao = &lcp_allowoptions[f->unit];
1833     int cilen, citype, cichar;	/* Parsed len, type, char value */
1834     u_short cishort;		/* Parsed short value */
1835     u_int32_t cilong;		/* Parse long value */
1836     int ret, newret;
1837     u_char *p0, *nakp, *rejp, *prev;
1838     int len;
1839 
1840     /*
1841      * Loop through options once to find out if peer is offering
1842      * Multilink, and repair values as needed.
1843      */
1844     ao->mru = ao->mrru;
1845     p0 = p;
1846     for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1847 	if (len < 2 || p[1] > len) {
1848 	    /*
1849 	     * RFC 1661 page 40 -- if the option extends beyond the
1850 	     * packet, then discard the entire packet.
1851 	     */
1852 	    dbglog("discarding LCP Configure-Request due to truncated option");
1853 	    return (0);
1854 	}
1855 	prev = p;
1856 	GETCHAR(citype, p);
1857 	GETCHAR(cilen, p);
1858 	if (citype == CI_MRRU) {
1859 	    if (ao->mrru != 0) {
1860 		if (ao->mrru+6 > PPP_MTU)
1861 		    ao->mru = PPP_MTU;
1862 		else
1863 		    ao->mru = ao->mrru + 6;
1864 	    }
1865 	}
1866 	if (cilen < 2)
1867 	    cilen = 2;
1868     }
1869     if (ao->mru > absmax_mtu)
1870 	ao->mru = absmax_mtu;
1871 
1872     ret = CODE_CONFACK;
1873     rejp = p = p0;
1874     nakp = nak_buffer;
1875 
1876     /*
1877      * Reset all its options.
1878      */
1879     BZERO(ho, sizeof(*ho));
1880 
1881     /*
1882      * Process all its options.
1883      */
1884     for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1885 	newret = CODE_CONFACK;			/* Assume success */
1886 
1887 	prev = p;
1888 	GETCHAR(citype, p);
1889 	GETCHAR(cilen, p);
1890 
1891 	switch (citype) {		/* Check CI type */
1892 	case CI_MRU:
1893 	    if (!ao->neg_mru) {
1894 		newret = CODE_CONFREJ;
1895 		break;
1896 	    }
1897 
1898 	    if (cilen != CILEN_SHORT) {	/* Check CI length */
1899 		newret = CODE_CONFNAK;
1900 		cishort = ao->mru;
1901 	    } else {
1902 		/* extract the MRU from the option */
1903 		GETSHORT(cishort, p);
1904 
1905 		/*
1906 		 * If the offered MRU is less than our desired MTU, we
1907 		 * should nak.  This is especially helpful if we're
1908 		 * doing demand-dial, since those queued up packets
1909 		 * might be discarded otherwise.
1910 		 */
1911 		if (cishort < ao->mru) {
1912 		    newret = CODE_CONFNAK;
1913 		    cishort = ao->mru;
1914 		}
1915 	    }
1916 
1917 	    /*
1918 	     * If we're going to send a nak with something less than
1919 	     * or equal to the default PPP MTU, then just reject instead.
1920 	     */
1921 	    if (newret == CODE_CONFNAK && cishort <= PPP_MTU)
1922 		newret = CODE_CONFREJ;
1923 
1924 	    if (newret == CODE_CONFNAK) {
1925 		PUTCHAR(CI_MRU, nakp);
1926 		PUTCHAR(CILEN_SHORT, nakp);
1927 		PUTSHORT(cishort, nakp);	/* Give it a hint */
1928 	    }
1929 
1930 	    ho->neg_mru = 1;		/* Remember that it sent MRU */
1931 	    ho->mru = cishort;		/* And remember value */
1932 	    break;
1933 
1934 	case CI_ASYNCMAP:
1935 	    if (!ao->neg_asyncmap) {
1936 		newret = CODE_CONFREJ;
1937 		break;
1938 	    }
1939 
1940 	    if (cilen != CILEN_LONG) {
1941 		newret = CODE_CONFNAK;
1942 		cilong = 0;
1943 	    } else {
1944 		GETLONG(cilong, p);
1945 
1946 		/*
1947 		 * Asyncmap must have set at least the bits
1948 		 * which are set in lcp_allowoptions[unit].asyncmap.
1949 		 */
1950 		if ((ao->asyncmap & ~cilong) != 0)
1951 		    newret = CODE_CONFNAK;
1952 	    }
1953 
1954 	    /*
1955 	     * Workaround for common broken Microsoft software -- if
1956 	     * the peer is sending us a nonzero ACCM, then it *needs*
1957 	     * us to send the same to it.  Adjust our Configure-
1958 	     * Request message and restart LCP.
1959 	     */
1960 	    if (do_msft_workaround && (cilong & ~wo->asyncmap)) {
1961 		dbglog("adjusted requested asyncmap from %X to %X",
1962 		    wo->asyncmap, wo->asyncmap | cilong);
1963 		do_msft_workaround = 0;
1964 		wo->neg_asyncmap = 1;
1965 		wo->asyncmap |= cilong;
1966 		f->flags &= ~OPT_SILENT;
1967 		info("possibly broken peer detected; restarting LCP");
1968 		fsm_lowerdown(f);
1969 		fsm_lowerup(f);
1970 		return (0);
1971 	    }
1972 
1973 	    if (newret == CODE_CONFNAK) {
1974 		PUTCHAR(CI_ASYNCMAP, nakp);
1975 		PUTCHAR(CILEN_LONG, nakp);
1976 		PUTLONG(ao->asyncmap | cilong, nakp);
1977 	    }
1978 	    ho->neg_asyncmap = 1;
1979 	    ho->asyncmap = cilong;
1980 	    break;
1981 
1982 	case CI_AUTHTYPE:
1983 	    if (!(ao->neg_upap || ao->neg_chap || ao->neg_mschap ||
1984 	        ao->neg_mschapv2)) {
1985 		rejected_peers_auth = 1;
1986 		if (cilen >= CILEN_SHORT) {
1987 		    GETSHORT(rejected_auth_proto, p);
1988 		} else {
1989 		    rejected_auth_proto = 0;
1990 		}
1991 		/*
1992 		 * Reject the option if we're not willing to authenticate.
1993 		 */
1994 		newret = CODE_CONFREJ;
1995 		break;
1996 	    }
1997 	    rejected_peers_auth = 0;
1998 	    naked_peers_auth = 0;
1999 
2000 	    if (cilen >= CILEN_SHORT) {
2001 		/* Extract the authentication protocol from the option */
2002 		GETSHORT(cishort, p);
2003 
2004 		if (ho->neg_upap || ho->neg_chap || ho->neg_mschap ||
2005 		    ho->neg_mschapv2) {
2006 		    dbglog("Rejecting extra authentication protocol option");
2007 		    newret = CODE_CONFREJ;
2008 		    break;
2009 		}
2010 
2011 		/*
2012 		 * Authtype must be PAP or CHAP.
2013 		 *
2014 		 * Note: if both ao->neg_upap and ao->neg_*chap* are
2015 		 * set, and the peer sends a Configure-Request with
2016 		 * two authenticate-protocol requests, one for CHAP
2017 		 * and one for UPAP, then we will reject the second
2018 		 * request.  Whether we end up doing CHAP or UPAP
2019 		 * depends then on the ordering of the CIs in the
2020 		 * peer's Configure-Request.
2021 		 *
2022 		 * We're supposed to list all of the protocols we can
2023 		 * possibly use in the returned Configure-Nak.  This
2024 		 * part of RFC 1661 (section 5.3) is in conflict with
2025 		 * the section that says the options shouldn't be
2026 		 * reordered, so it's often ignored.
2027 		 */
2028 
2029 		if (cishort == PPP_PAP) {
2030 		    if (ao->neg_upap) {
2031 			if (cilen != CILEN_SHORT)
2032 			    goto try_pap_anyway;
2033 			ho->neg_upap = 1;
2034 			break;
2035 		    }
2036 		} else if (cishort == PPP_CHAP) {
2037 		    /* Test >= here to allow for broken peers. */
2038 		    if (cilen >= CILEN_CHAP &&
2039 			(ao->neg_chap || ao->neg_mschap || ao->neg_mschapv2)) {
2040 			GETCHAR(cichar, p);
2041 			if (cichar == CHAP_DIGEST_MD5 && ao->neg_chap)
2042 			    ho->neg_chap = 1;
2043 			else if (cichar == CHAP_MICROSOFT && ao->neg_mschap)
2044 			    ho->neg_mschap = 1;
2045 			else if (cichar == CHAP_MICROSOFT_V2 &&
2046 			    ao->neg_mschapv2)
2047 			    ho->neg_mschap = 1;
2048 			if (ho->neg_chap || ho->neg_mschap ||
2049 			    ho->neg_mschapv2) {
2050 			    ho->chap_mdtype = cichar; /* save md type */
2051 			    break;
2052 			}
2053 		    }
2054 		}
2055 	    }
2056 
2057 	    /*
2058 	     * We don't recognize the protocol they're asking for.
2059 	     * Nak it with something we're willing to do.
2060 	     * (At this point we know ao->neg_upap || ao->neg_chap.)
2061 	     */
2062 	    PUTCHAR(CI_AUTHTYPE, nakp);
2063 	    if (ao->neg_chap || ao->neg_mschap || ao->neg_mschapv2) {
2064 		PUTCHAR(CILEN_CHAP, nakp);
2065 		PUTSHORT(PPP_CHAP, nakp);
2066 		PUTCHAR(ao->chap_mdtype, nakp);
2067 		naked_auth_proto = PPP_CHAP;
2068 	    } else {
2069 	    try_pap_anyway:
2070 		PUTCHAR(CILEN_SHORT, nakp);
2071 		PUTSHORT(PPP_PAP, nakp);
2072 		naked_auth_proto = PPP_PAP;
2073 	    }
2074 	    naked_peers_auth = 1;
2075 	    naked_auth_orig = cishort;
2076 	    newret = CODE_CONFNAK;
2077 	    break;
2078 
2079 	case CI_QUALITY:
2080 	    if (!ao->neg_lqr) {
2081 		newret = CODE_CONFREJ;
2082 		break;
2083 	    }
2084 
2085 	    if (cilen != CILEN_LQR) {
2086 		newret = CODE_CONFNAK;
2087 		cilong = ao->lqr_period;
2088 	    } else {
2089 
2090 		GETSHORT(cishort, p);
2091 		GETLONG(cilong, p);
2092 
2093 		/* Check the LQM protocol */
2094 		if (cishort != PPP_LQR) {
2095 		    newret = CODE_CONFNAK;
2096 		}
2097 
2098 		/* Check the reporting period; we can't both send zero */
2099 		if ((cilong == 0 && go->lqr_period == 0) ||
2100 		    cilong < ao->lqr_period) {
2101 		    newret = CODE_CONFNAK;
2102 		    if ((cilong = ao->lqr_period) == 0)
2103 			cilong = 500;
2104 		}
2105 	    }
2106 
2107 	    if (newret == CODE_CONFNAK) {
2108 		PUTCHAR(CI_QUALITY, nakp);
2109 		PUTCHAR(CILEN_LQR, nakp);
2110 		PUTSHORT(PPP_LQR, nakp);
2111 		PUTLONG(cilong, nakp);
2112 	    }
2113 
2114 	    ho->neg_lqr = 1;
2115 	    ho->lqr_period = cilong;
2116 	    break;
2117 
2118 	case CI_MAGICNUMBER:
2119 	    if (!(ao->neg_magicnumber || go->neg_magicnumber)) {
2120 		newret = CODE_CONFREJ;
2121 		break;
2122 	    }
2123 
2124 	    ho->neg_magicnumber = 1;
2125 	    if (cilen < CILEN_LONG) {
2126 		/*
2127 		 * If we send Magic-Number, then we must not reject it
2128 		 * when the peer sends it to us, even if its version
2129 		 * looks odd to us.  Ack if the cilent is wrong in this
2130 		 * case.  If we're not sending Magic-Number, then we don't
2131 		 * much care what its value is anyway.
2132 		 */
2133 		break;
2134 	    }
2135 
2136 	    GETLONG(cilong, p);
2137 	    ho->magicnumber = cilong;
2138 	    if (cilen > CILEN_LONG)
2139 		break;
2140 
2141 	    /*
2142 	     * It must have a different magic number.  Make sure we
2143 	     * give it a good one to use.
2144 	     */
2145 	    while (go->neg_magicnumber && cilong == go->magicnumber) {
2146 		newret = CODE_CONFNAK;
2147 		cilong = magic();
2148 	    }
2149 
2150 	    if (newret == CODE_CONFNAK) {
2151 		PUTCHAR(CI_MAGICNUMBER, nakp);
2152 		PUTCHAR(CILEN_LONG, nakp);
2153 		PUTLONG(cilong, nakp);
2154 		/*
2155 		 * We don't need to bump the numloops counter here
2156 		 * since it's already done upon reception of a nak.
2157 		 */
2158 	    }
2159 	    break;
2160 
2161 	case CI_PCOMPRESSION:
2162 	    if (!ao->neg_pcompression) {
2163 		newret = CODE_CONFREJ;
2164 		break;
2165 	    }
2166 	    if (cilen != CILEN_VOID) {
2167 		newret = CODE_CONFNAK;
2168 		PUTCHAR(CI_PCOMPRESSION, nakp);
2169 		PUTCHAR(CILEN_VOID, nakp);
2170 	    }
2171 	    ho->neg_pcompression = 1;
2172 	    break;
2173 
2174 	case CI_ACCOMPRESSION:
2175 	    if (!ao->neg_accompression) {
2176 		newret = CODE_CONFREJ;
2177 		break;
2178 	    }
2179 	    if (cilen != CILEN_VOID) {
2180 		newret = CODE_CONFNAK;
2181 		PUTCHAR(CI_ACCOMPRESSION, nakp);
2182 		PUTCHAR(CILEN_VOID, nakp);
2183 	    }
2184 	    ho->neg_accompression = 1;
2185 	    break;
2186 
2187 	case CI_FCSALTERN:
2188 	    if (!ao->neg_fcs) {
2189 		newret = CODE_CONFREJ;
2190 		break;
2191 	    }
2192 
2193 	    if (cilen != CILEN_CHAR) {
2194 		newret = CODE_CONFNAK;
2195 		cichar = ao->fcs_type;
2196 	    } else {
2197 
2198 		GETCHAR(cichar, p);
2199 		/* If it has bits we don't like, tell it to stop. */
2200 		if (cichar & ~ao->fcs_type) {
2201 		    if ((cichar &= ao->fcs_type) == 0) {
2202 			newret = CODE_CONFREJ;
2203 			break;
2204 		    }
2205 		    newret = CODE_CONFNAK;
2206 		}
2207 	    }
2208 	    if (newret == CODE_CONFNAK) {
2209 		PUTCHAR(CI_FCSALTERN, nakp);
2210 		PUTCHAR(CILEN_CHAR, nakp);
2211 		PUTCHAR(cichar, nakp);
2212 	    }
2213 	    ho->neg_fcs = 1;
2214 	    ho->fcs_type = cichar;
2215 	    break;
2216 
2217 	case CI_MRRU:
2218 	    if (!ao->neg_mrru || !multilink) {
2219 		newret = CODE_CONFREJ;
2220 		break;
2221 	    }
2222 	    if (cilen != CILEN_SHORT) {
2223 		newret = CODE_CONFNAK;
2224 		cishort = ao->mrru;
2225 	    } else {
2226 		GETSHORT(cishort, p);
2227 		if (cishort < ao->mrru) {
2228 		    newret = CODE_CONFNAK;
2229 		    cishort = ao->mrru;
2230 		}
2231 	    }
2232 
2233 	    if (cishort < PPP_MINMTU) {
2234 		newret = CODE_CONFNAK;
2235 		cishort = PPP_MINMTU;
2236 	    }
2237 
2238 	    if (newret == CODE_CONFNAK) {
2239 		PUTCHAR(CI_MRRU, nakp);
2240 		PUTCHAR(CILEN_SHORT, nakp);
2241 		PUTSHORT(cishort, nakp);
2242 	    }
2243 
2244 	    ho->neg_mrru = 1;
2245 	    ho->mrru = cishort;
2246 	    break;
2247 
2248 	case CI_SSNHF:
2249 	    if (!ao->neg_ssnhf || !multilink) {
2250 		newret = CODE_CONFREJ;
2251 		break;
2252 	    }
2253 	    if (cilen != CILEN_VOID) {
2254 		newret = CODE_CONFNAK;
2255 		PUTCHAR(CI_SSNHF, nakp);
2256 		PUTCHAR(CILEN_VOID, nakp);
2257 	    }
2258 	    ho->neg_ssnhf = 1;
2259 	    break;
2260 
2261 	case CI_EPDISC:
2262 	    if (!ao->neg_endpoint) {
2263 		newret = CODE_CONFREJ;
2264 		break;
2265 	    }
2266 	    if (cilen < CILEN_CHAR || cilen > CILEN_CHAR + MAX_ENDP_LEN) {
2267 		int i;
2268 
2269 		newret = CODE_CONFNAK;
2270 		PUTCHAR(CI_EPDISC, nakp);
2271 		PUTCHAR(CILEN_CHAR + ao->endpoint.length, nakp);
2272 		PUTCHAR(ao->endpoint.class, nakp);
2273 		for (i = 0; i < ao->endpoint.length; i++)
2274 		    PUTCHAR(ao->endpoint.value[i], nakp);
2275 		break;
2276 	    }
2277 	    GETCHAR(cichar, p);
2278 	    ho->neg_endpoint = 1;
2279 	    ho->endpoint.class = cichar;
2280 	    ho->endpoint.length = cilen - 3;
2281 	    BCOPY(p, ho->endpoint.value, cilen - 3);
2282 	    break;
2283 
2284 #ifdef MUX_FRAME
2285         case CI_MUXING:
2286             if (ao->pppmux == 0 || cilen != CILEN_VOID) {
2287                 newret = CODE_CONFREJ;
2288                 break;
2289             }
2290             /* remember its option */
2291             ho->pppmux = ao->pppmux;
2292             break;
2293 #endif
2294 
2295 	default:
2296 	    dbglog("LCP: rejecting unknown option %d", citype);
2297 	    newret = CODE_CONFREJ;
2298 	    break;
2299 	}
2300 
2301 	/* Cope with confused peers. */
2302 	if (cilen < 2)
2303 	    cilen = 2;
2304 
2305 	/*
2306 	 * If this is an Ack'able CI, but we're sending back a Nak,
2307 	 * don't include this CI.
2308 	 */
2309 	if (newret == CODE_CONFACK && ret != CODE_CONFACK)
2310 	    continue;
2311 
2312 	if (newret == CODE_CONFNAK) {
2313 	    /*
2314 	     * Continue naking the Magic Number option until the cows come
2315 	     * home -- rejecting it is wrong.
2316 	     */
2317 	    if (dont_nak && citype != CI_MAGICNUMBER) {
2318 		newret = CODE_CONFREJ;
2319 	    } else {
2320 		/* Ignore subsequent Nak'able things if rejecting. */
2321 		if (ret == CODE_CONFREJ)
2322 		    continue;
2323 		ret = CODE_CONFNAK;
2324 	    }
2325 	}
2326 
2327 	if (newret == CODE_CONFREJ) {
2328 	    ret = CODE_CONFREJ;
2329 	    if (prev != rejp)
2330 		BCOPY(prev, rejp, cilen);
2331 	    rejp += cilen;
2332 	}
2333     }
2334 
2335     /*
2336      * If the peer hasn't negotiated its MRU, and we'd like an MTU
2337      * that's larger than the default, try sending an unsolicited
2338      * Nak for what we want.
2339      */
2340     if (ret != CODE_CONFREJ && !ho->neg_mru && ao->mru > PPP_MTU &&
2341 	!dont_nak && unsolicit_mru) {
2342 	unsolicit_mru = 0;	/* don't ask again */
2343 	ret = CODE_CONFNAK;
2344 	PUTCHAR(CI_MRU, nakp);
2345 	PUTCHAR(CILEN_SHORT, nakp);
2346 	PUTSHORT(ao->mru, nakp);
2347     }
2348 
2349     switch (ret) {
2350     case CODE_CONFACK:
2351 	*lenp = p - p0;
2352 	break;
2353     case CODE_CONFNAK:
2354 	/*
2355 	 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
2356 	 */
2357 	*lenp = nakp - nak_buffer;
2358 	BCOPY(nak_buffer, p0, *lenp);
2359 	break;
2360     case CODE_CONFREJ:
2361 	*lenp = rejp - p0;
2362 
2363 	/* We're about to send Configure-Reject; send Identification */
2364 	if (!noident && sentident < 3) {
2365 	    LcpSendIdentification(f);
2366 	    sentident++;
2367 	}
2368 	break;
2369     }
2370 
2371     LCPDEBUG(("lcp_reqci: returning %s.", code_name(ret, 1)));
2372     return (ret);			/* Return final code */
2373 }
2374 
2375 
2376 /*
2377  * lcp_up - LCP has come UP.
2378  */
2379 static void
2380 lcp_up(f)
2381     fsm *f;
2382 {
2383     lcp_options *wo = &lcp_wantoptions[f->unit];
2384     lcp_options *ho = &lcp_hisoptions[f->unit];
2385     lcp_options *go = &lcp_gotoptions[f->unit];
2386     lcp_options *ao = &lcp_allowoptions[f->unit];
2387     int mru, mtu;
2388 
2389     if (!go->neg_magicnumber)
2390 	go->magicnumber = 0;
2391     if (!ho->neg_magicnumber)
2392 	ho->magicnumber = 0;
2393 
2394     /*
2395      * Set our MTU to the smaller of the MTU we wanted and
2396      * the MRU our peer wanted.  If we negotiated an MRU,
2397      * set our MRU to the larger of value we wanted and
2398      * the value we got in the negotiation.
2399      */
2400     if (ao->mru != 0 && ho->mru > ao->mru)
2401 	ho->mru = ao->mru;
2402     mtu = (ho->neg_mru ? ho->mru: PPP_MRU);
2403     if (mtu > absmax_mtu)
2404 	mtu = absmax_mtu;
2405     ppp_send_config(f->unit, mtu,
2406 		    (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
2407 		    ho->neg_pcompression, ho->neg_accompression);
2408     fsm_setpeermru(f->unit, mtu);
2409     mru = (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU);
2410     if (mru > absmax_mru)
2411 	mru = absmax_mru;
2412     ppp_recv_config(f->unit, mru,
2413 		    (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
2414 		    go->neg_pcompression, go->neg_accompression);
2415 #ifdef NEGOTIATE_FCS
2416     ppp_send_fcs(f->unit, ho->neg_fcs ? ho->fcs_type : FCSALT_16);
2417     ppp_recv_fcs(f->unit, go->neg_fcs ? go->fcs_type : FCSALT_16);
2418 #endif
2419 #ifdef MUX_FRAME
2420     ppp_send_muxoption(f->unit, ho->pppmux);
2421     ppp_recv_muxoption(f->unit, go->pppmux);
2422 #endif
2423 
2424     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
2425 
2426     /* LCP is Up; send Identification */
2427     if (!noident) {
2428 	LcpSendIdentification(f);
2429 	sentident++;
2430     }
2431 
2432     link_established(f->unit);
2433 }
2434 
2435 
2436 /*
2437  * lcp_down - LCP has gone DOWN.
2438  *
2439  * Alert other protocols.
2440  */
2441 static void
2442 lcp_down(f)
2443     fsm *f;
2444 {
2445     int mtu;
2446     lcp_options *go = &lcp_gotoptions[f->unit];
2447 
2448     lcp_echo_lowerdown(f->unit);
2449 
2450     link_down(f->unit);
2451 
2452     mtu = PPP_MTU > absmax_mtu ? absmax_mtu : PPP_MTU;
2453     ppp_send_config(f->unit, mtu, 0xffffffff, 0, 0);
2454     ppp_recv_config(f->unit, (PPP_MRU > absmax_mru ? absmax_mru : PPP_MRU),
2455 		    (go->neg_asyncmap? go->asyncmap: 0xffffffff),
2456 		    go->neg_pcompression, go->neg_accompression);
2457 #ifdef NEGOTIATE_FCS
2458     ppp_send_fcs(f->unit, FCSALT_16);
2459     ppp_recv_fcs(f->unit, FCSALT_16);
2460 #endif
2461     fsm_setpeermru(f->unit, mtu);
2462 }
2463 
2464 
2465 /*
2466  * lcp_starting - LCP needs the lower layer up.
2467  */
2468 static void
2469 lcp_starting(f)
2470     fsm *f;
2471 {
2472     link_required(f->unit);
2473 }
2474 
2475 
2476 /*
2477  * lcp_finished - LCP has finished with the lower layer.
2478  */
2479 static void
2480 lcp_finished(f)
2481     fsm *f;
2482 {
2483     link_terminated(f->unit);
2484 }
2485 
2486 
2487 /*
2488  * lcp_printpkt - print the contents of an LCP packet.
2489  */
2490 
2491 static int
2492 lcp_printpkt(p, plen, printer, arg)
2493     u_char *p;
2494     int plen;
2495     void (*printer) __P((void *, const char *, ...));
2496     void *arg;
2497 {
2498     int code, id, len, olen, i;
2499     u_char *pstart, *optend, cichar;
2500     u_short cishort;
2501     u_int32_t cilong;
2502 
2503     if (plen < HEADERLEN)
2504 	return 0;
2505     pstart = p;
2506     GETCHAR(code, p);
2507     GETCHAR(id, p);
2508     GETSHORT(len, p);
2509     if (len < HEADERLEN || len > plen)
2510 	return 0;
2511 
2512     printer(arg, " %s id=0x%x", code_name(code,1), id);
2513     len -= HEADERLEN;
2514     switch (code) {
2515     case CODE_CONFREQ:
2516     case CODE_CONFACK:
2517     case CODE_CONFNAK:
2518     case CODE_CONFREJ:
2519 	/* print option list */
2520 	while (len >= 2) {
2521 	    GETCHAR(code, p);
2522 	    GETCHAR(olen, p);
2523 	    p -= 2;
2524 	    if (olen < 2 || olen > len) {
2525 		break;
2526 	    }
2527 	    printer(arg, " <");
2528 	    len -= olen;
2529 	    optend = p + olen;
2530 	    switch (code) {
2531 	    case CI_MRU:
2532 		if (olen >= CILEN_SHORT) {
2533 		    p += 2;
2534 		    GETSHORT(cishort, p);
2535 		    printer(arg, "mru %d", cishort);
2536 		}
2537 		break;
2538 	    case CI_ASYNCMAP:
2539 		if (olen >= CILEN_LONG) {
2540 		    p += 2;
2541 		    GETLONG(cilong, p);
2542 		    printer(arg, "asyncmap 0x%x", cilong);
2543 		}
2544 		break;
2545 	    case CI_AUTHTYPE:
2546 		if (olen >= CILEN_SHORT) {
2547 		    p += 2;
2548 		    printer(arg, "auth ");
2549 		    GETSHORT(cishort, p);
2550 		    switch (cishort) {
2551 		    case PPP_PAP:
2552 			printer(arg, "pap");
2553 			break;
2554 		    case PPP_CHAP:
2555 			printer(arg, "chap");
2556 			if (p < optend) {
2557 			    switch (*p) {
2558 			    case CHAP_DIGEST_MD5:
2559 				printer(arg, " MD5");
2560 				++p;
2561 				break;
2562 			    case CHAP_MICROSOFT:
2563 				printer(arg, " m$oft");
2564 				++p;
2565 				break;
2566 			    case CHAP_MICROSOFT_V2:
2567 				printer(arg, " m$oft-v2");
2568 				++p;
2569 				break;
2570 			    }
2571 			}
2572 			break;
2573 #ifdef PPP_EAP
2574 		    case PPP_EAP:
2575 			printer(arg, "eap");
2576 			break;
2577 #endif
2578 		    case 0xC027:
2579 			printer(arg, "spap");
2580 			break;
2581 		    case 0xC123:
2582 			printer(arg, "old-spap");
2583 			break;
2584 		    default:
2585 			printer(arg, "0x%x", cishort);
2586 		    }
2587 		}
2588 		break;
2589 	    case CI_QUALITY:
2590 		if (olen >= CILEN_SHORT) {
2591 		    p += 2;
2592 		    printer(arg, "quality ");
2593 		    GETSHORT(cishort, p);
2594 		    switch (cishort) {
2595 		    case PPP_LQR:
2596 			printer(arg, "lqr");
2597 			break;
2598 		    default:
2599 			printer(arg, "0x%x", cishort);
2600 		    }
2601 		}
2602 		break;
2603 	    case CI_CALLBACK:
2604 		if (olen >= CILEN_CHAR) {
2605 		    p += 2;
2606 		    printer(arg, "callback ");
2607 		    GETCHAR(cichar, p);
2608 		    if (cichar <= 6 &&
2609 			*callback_strings[(int)cichar] != '\0') {
2610 			printer(arg, "%s", callback_strings[(int)cichar]);
2611 		    } else {
2612 			printer(arg, "0x%x", cichar);
2613 		    }
2614 		}
2615 		break;
2616 	    case CI_MAGICNUMBER:
2617 		if (olen >= CILEN_LONG) {
2618 		    p += 2;
2619 		    GETLONG(cilong, p);
2620 		    printer(arg, "magic 0x%x", cilong);
2621 		}
2622 		break;
2623 	    case CI_PCOMPRESSION:
2624 		if (olen >= CILEN_VOID) {
2625 		    p += 2;
2626 		    printer(arg, "pcomp");
2627 		}
2628 		break;
2629 	    case CI_ACCOMPRESSION:
2630 		if (olen >= CILEN_VOID) {
2631 		    p += 2;
2632 		    printer(arg, "accomp");
2633 		}
2634 		break;
2635 	    case CI_FCSALTERN:
2636 		if (olen >= CILEN_CHAR) {
2637 		    char **cpp;
2638 		    int needcomma = 0;
2639 
2640 		    p += 2;
2641 		    GETCHAR(cichar, p);
2642 		    for (cpp = fcsalt_strings; *cpp != NULL; cpp++)
2643 			if (cichar & 1<<(cpp-fcsalt_strings)) {
2644 			    cichar &= ~(1<<(cpp-fcsalt_strings));
2645 			    printer(arg, (needcomma ? ",%s" : "fcs %s"), *cpp);
2646 			    needcomma = 1;
2647 			}
2648 		    if (cichar != 0 || !needcomma)
2649 			printer(arg, (needcomma ? ",0x%x" : "fcs 0x%x"),
2650 			    cichar);
2651 		}
2652 		break;
2653 	    case CI_NUMBERED:
2654 		if (olen >= CILEN_SHORT) {
2655 		    p += 2;
2656 		    GETCHAR(cichar, p);
2657 		    printer(arg, "numb win %d", cichar);
2658 		    GETCHAR(cichar, p);
2659 		    printer(arg, " addr %d", cichar);
2660 		}
2661 		break;
2662 	    case CI_MRRU:
2663 		if (olen >= CILEN_SHORT) {
2664 		    p += 2;
2665 		    GETSHORT(cishort, p);
2666 		    printer(arg, "mrru %d", cishort);
2667 		}
2668 		break;
2669 	    case CI_SSNHF:
2670 		if (olen >= CILEN_VOID) {
2671 		    p += 2;
2672 		    printer(arg, "ssnhf");
2673 		}
2674 		break;
2675 	    case CI_EPDISC:
2676 		if (olen >= CILEN_CHAR) {
2677 		    struct epdisc epd;
2678 		    p += 2;
2679 		    GETCHAR(epd.class, p);
2680 		    epd.length = olen - CILEN_CHAR;
2681 		    if (epd.length > MAX_ENDP_LEN)
2682 			epd.length = MAX_ENDP_LEN;
2683 		    if (epd.length > 0) {
2684 			BCOPY(p, epd.value, epd.length);
2685 			p += epd.length;
2686 		    }
2687 		    printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
2688 		}
2689 		break;
2690 	    case CI_LINKDISC:
2691 		if (olen >= CILEN_SHORT) {
2692 		    p += 2;
2693 		    GETSHORT(cishort, p);
2694 		    printer(arg, "linkdisc %d", cishort);
2695 		}
2696 		break;
2697 	    case CI_COBS:
2698 		if (olen >= CILEN_CHAR) {
2699 		    p += 2;
2700 		    GETCHAR(cichar, p);
2701 		    printer(arg, "cobs 0x%x", cichar);
2702 		}
2703 		break;
2704 	    case CI_PFXELISION:
2705 		if (olen >= CILEN_CHAR) {
2706 		    p += 2;
2707 		    printer(arg, "pfx");
2708 		}
2709 		break;
2710 	    case CI_MPHDRFMT:
2711 		if (olen >= CILEN_SHORT) {
2712 		    p += 2;
2713 		    printer(arg, "mphdr ");
2714 		    GETCHAR(cichar, p);
2715 		    switch (cichar) {
2716 		    case 2:
2717 			    printer(arg, "long");
2718 			    break;
2719 		    case 6:
2720 			    printer(arg, "short");
2721 			    break;
2722 		    default:
2723 			    printer(arg, "0x%x", cichar);
2724 			    break;
2725 		    }
2726 		    GETCHAR(cichar, p);
2727 		    printer(arg, " #cl %d", cichar);
2728 		}
2729 		break;
2730 	    case CI_I18N:
2731 		if (olen >= CILEN_LONG) {
2732 		    p += 2;
2733 		    GETLONG(cilong, p);
2734 		    printer(arg, "i18n charset 0x%x", cilong);
2735 		    if (olen > CILEN_LONG) {
2736 			printer(arg, " lang ");
2737 			print_string((char *)p, olen-CILEN_LONG, printer, arg);
2738 			p = optend;
2739 		    }
2740 		}
2741 		break;
2742 	    case CI_SDL:
2743 		if (olen >= CILEN_VOID) {
2744 		    p += 2;
2745 		    printer(arg, "sdl");
2746 		}
2747 		break;
2748 	    case CI_MUXING:
2749 		if (olen >= CILEN_VOID) {
2750 		    p += 2;
2751 		    printer(arg, "mux");
2752 		}
2753 		break;
2754 	    }
2755 	    while (p < optend) {
2756 		GETCHAR(code, p);
2757 		printer(arg, " %.2x", code);
2758 	    }
2759 	    printer(arg, ">");
2760 	}
2761 	break;
2762 
2763     case CODE_TERMACK:
2764     case CODE_TERMREQ:
2765 	if (len > 0 && *p >= ' ' && *p < 0x7f) {
2766 	    printer(arg, " ");
2767 	    print_string((char *)p, len, printer, arg);
2768 	    p += len;
2769 	    len = 0;
2770 	}
2771 	break;
2772 
2773     case CODE_ECHOREQ:
2774     case CODE_ECHOREP:
2775     case CODE_DISCREQ:
2776 	if (len >= 4) {
2777 	    GETLONG(cilong, p);
2778 	    printer(arg, " magic=0x%x", cilong);
2779 	    len -= 4;
2780 	}
2781 	break;
2782 
2783     case CODE_IDENT:
2784 	if (len >= 4) {
2785 	    GETLONG(cilong, p);
2786 	    printer(arg, " magic=0x%x", cilong);
2787 	    len -= 4;
2788 	} else
2789 	    break;
2790 	if (len > 0 && (len > 1 || *p != '\0')) {
2791 	    printer(arg, " ");
2792 	    print_string((char *)p, len, printer, arg);
2793 	    p += len;
2794 	    len = 0;
2795 	}
2796 	break;
2797 
2798     case CODE_TIMEREMAIN:
2799 	if (len >= 4) {
2800 	    GETLONG(cilong, p);
2801 	    printer(arg, " magic=0x%x", cilong);
2802 	    len -= 4;
2803 	} else
2804 	    break;
2805 	if (len >= 4) {
2806 	    GETLONG(cilong, p);
2807 	    printer(arg, " seconds=%d", cilong);
2808 	    len -= 4;
2809 	} else
2810 	    break;
2811 	if (len > 0 && (len > 1 || *p != '\0')) {
2812 	    printer(arg, " ");
2813 	    print_string((char *)p, len, printer, arg);
2814 	    p += len;
2815 	    len = 0;
2816 	}
2817 	break;
2818     }
2819 
2820     /* print the rest of the bytes in the packet */
2821     for (i = 0; i < len && i < 32; ++i) {
2822 	GETCHAR(code, p);
2823 	printer(arg, " %.2x", code);
2824     }
2825     if (i < len) {
2826 	printer(arg, " ...");
2827 	p += len - i;
2828     }
2829 
2830     return p - pstart;
2831 }
2832 
2833 /*
2834  * Time to shut down the link because there is nothing out there.
2835  */
2836 
2837 static void
2838 LcpLinkFailure (f)
2839     fsm *f;
2840 {
2841     char *close_message;
2842 
2843     if (f->state == OPENED) {
2844 	if (lcp_echo_badreplies > LCP_ECHO_MAX_BADREPLIES) {
2845 	    info("Received %d bad echo-replies", lcp_echo_badreplies);
2846 	    close_message = "Receiving malformed Echo-Replies";
2847 	} else if (lcp_echo_accm_test) {
2848 	    /*
2849 	     * If this is an asynchronous line and we've missed all of
2850 	     * the initial echo requests, then this is probably due to
2851 	     * a bad ACCM.
2852 	     */
2853 	    notice("Peer not responding to initial Echo-Requests.");
2854 	    notice("Negotiated asyncmap may be incorrect for this link.");
2855 	    close_message = "Peer not responding; perhaps bad asyncmap";
2856 	} else {
2857 	    info("No response to %d echo-requests", lcp_echos_pending);
2858 	    notice("Serial link appears to be disconnected.");
2859 	    close_message = "Peer not responding";
2860 	}
2861 
2862 	lcp_close(f->unit, close_message);
2863 	status = EXIT_PEER_DEAD;
2864     }
2865 }
2866 
2867 /*
2868  * Timer expired for the LCP echo requests from this process.
2869  */
2870 
2871 static void
2872 LcpEchoCheck (f)
2873     fsm *f;
2874 {
2875     if (f->state != OPENED || lcp_echo_interval == 0)
2876 	return;
2877 
2878     LcpSendEchoRequest (f);
2879 
2880     /*
2881      * Start the timer for the next interval.
2882      */
2883     if (lcp_echo_timer_running)
2884 	warn("assertion lcp_echo_timer_running==0 failed");
2885     TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
2886     lcp_echo_timer_running = 1;
2887 }
2888 
2889 /*
2890  * LcpEchoTimeout - Timer expired on the LCP echo
2891  */
2892 
2893 static void
2894 LcpEchoTimeout (arg)
2895     void *arg;
2896 {
2897     if (lcp_echo_timer_running != 0) {
2898         lcp_echo_timer_running = 0;
2899 	LcpEchoCheck ((fsm *) arg);
2900     }
2901 }
2902 
2903 /*
2904  * LcpEchoReply - LCP has received a reply to the echo
2905  */
2906 /*ARGSUSED*/
2907 static int
2908 lcp_received_echo_reply (f, id, inp, len)
2909     fsm *f;
2910     int id;
2911     u_char *inp;
2912     int len;
2913 {
2914     u_int32_t magic;
2915 
2916     /* Check the magic number - don't count replies from ourselves. */
2917     if (len < 4) {
2918 	dbglog("lcp: received short Echo-Reply, length %d", len);
2919 	return (0);
2920     }
2921     GETLONG(magic, inp);
2922     if (lcp_gotoptions[f->unit].neg_magicnumber &&
2923 	magic == lcp_gotoptions[f->unit].magicnumber) {
2924 	warn("appear to have received our own echo-reply!");
2925 	return (0);
2926     }
2927 
2928     /* Reset the number of outstanding echo frames */
2929     lcp_echos_pending = 0;
2930 
2931     if (lcp_echo_accm_test) {
2932 	dbglog("lcp: validated asyncmap setting");
2933 	lcp_echo_accm_test = 0;
2934 	if (lcp_echo_fails == 0)
2935 	    lcp_echo_interval = 0;
2936     }
2937     return (1);
2938 }
2939 
2940 /*
2941  * LcpSendEchoRequest - Send an echo request frame to the peer
2942  */
2943 
2944 static void
2945 LcpSendEchoRequest (f)
2946     fsm *f;
2947 {
2948     u_int32_t lcp_magic;
2949     u_char pkt[4+256], *pktp;
2950     int i;
2951 
2952     /*
2953      * Detect the failure of the peer at this point.  If we're not currently
2954      * performing the ACCM test, then we just check for the user's echo-failure
2955      * point.  If we are performing the ACCM test, then use ACCM_TEST_FAILS if
2956      * the user hasn't specified a different failure point.
2957      */
2958     i = lcp_echo_fails;
2959     if (i == 0)
2960 	i = ACCM_TEST_FAILS;
2961     if ((!lcp_echo_accm_test && lcp_echo_fails != 0 &&
2962 	lcp_echos_pending >= lcp_echo_fails) ||
2963 	(lcp_echo_accm_test && lcp_echos_pending >= i)) {
2964 	LcpLinkFailure(f);
2965 	lcp_echos_pending = 0;
2966 	lcp_echo_badreplies = 0;
2967     }
2968 
2969     /*
2970      * Make and send the echo request frame.
2971      */
2972     if (f->state == OPENED) {
2973         lcp_magic = lcp_gotoptions[f->unit].magicnumber;
2974 	pktp = pkt;
2975 	PUTLONG(lcp_magic, pktp);
2976 	/* Send some test packets so we can fail the link early. */
2977 	if (lcp_echo_accm_test) {
2978 	    switch (use_accm_test) {
2979 	    case 1:
2980 		/* Only the characters covered by negotiated ACCM */
2981 		for (i = 0; i < 32; i++)
2982 		    *pktp++ = i;
2983 		break;
2984 	    case 2:
2985 		/* All characters */
2986 		for (i = 0; i < 256; i++)
2987 		    *pktp++ = i;
2988 		break;
2989 	    }
2990 	}
2991         fsm_sdata(f, CODE_ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
2992 	++lcp_echos_pending;
2993     }
2994 }
2995 
2996 /*
2997  * lcp_echo_lowerup - Start the timer for the LCP frame
2998  */
2999 
3000 static void
3001 lcp_echo_lowerup (unit)
3002     int unit;
3003 {
3004     fsm *f = &lcp_fsm[unit];
3005 
3006     /* Clear the parameters for generating echo frames */
3007     lcp_echos_pending      = 0;
3008     lcp_echo_number        = 0;
3009     lcp_echo_timer_running = 0;
3010     lcp_echo_accm_test     = !sync_serial && use_accm_test;
3011 
3012     /* If a timeout interval is specified then start the timer */
3013     LcpEchoCheck(f);
3014 }
3015 
3016 /*
3017  * lcp_echo_lowerdown - Stop the timer for the LCP frame
3018  */
3019 
3020 static void
3021 lcp_echo_lowerdown (unit)
3022     int unit;
3023 {
3024     fsm *f = &lcp_fsm[unit];
3025 
3026     if (lcp_echo_timer_running != 0) {
3027         UNTIMEOUT (LcpEchoTimeout, f);
3028         lcp_echo_timer_running = 0;
3029     }
3030 }
3031 
3032 /*
3033  * LcpSendIdentification - Send LCP Identification string to peer.
3034  */
3035 
3036 static void
3037 LcpSendIdentification (f)
3038     fsm *f;
3039 {
3040     u_int32_t lcp_magic;
3041     u_char pkt[4 + sizeof(identstr)], *pktp;
3042     int idlen;
3043 
3044     /*
3045      * Make and send the Identification frame.
3046      */
3047     if (f->state == OPENED)
3048         lcp_magic = lcp_gotoptions[f->unit].magicnumber;
3049     else
3050 	lcp_magic = 0;
3051 
3052     pktp = pkt;
3053     PUTLONG(lcp_magic, pktp);
3054     idlen = strlen(identstr);
3055     BCOPY(identstr, pktp, idlen);
3056     INCPTR(idlen, pktp);
3057     fsm_sdata(f, CODE_IDENT, ++f->id, pkt, pktp - pkt);
3058 }
3059 
3060 /*ARGSUSED*/
3061 static void
3062 lcp_received_identification (f, id, inp, len)
3063     fsm *f;
3064     int id;
3065     u_char *inp;
3066     int len;
3067 {
3068     u_int32_t magic;
3069 
3070     /* Check the magic number - don't count replies from ourselves. */
3071     if (len < 4) {
3072 	dbglog("%s: received short Identification; %d < 4", len);
3073 	return;
3074     }
3075     GETLONG(magic, inp);
3076     len -= 4;
3077     if (lcp_gotoptions[f->unit].neg_magicnumber && f->state == OPENED &&
3078 	magic == lcp_gotoptions[f->unit].magicnumber) {
3079 	warn("appear to have received our own Identification!");
3080 	return;
3081     }
3082     if (len > 0 && (len > 1 || *inp != '\0'))
3083 	notice("Peer Identification: %0.*v", len, inp);
3084 }
3085 
3086 /*
3087  * Send a Time-Remaining LCP packet.  We don't include a message.
3088  */
3089 static void
3090 LcpSendTimeRemaining(f, time_remaining)
3091     fsm *f;
3092     u_int32_t time_remaining;
3093 {
3094     u_int32_t lcp_magic;
3095     u_char pkt[8];
3096     u_char *pktp;
3097 
3098     if (f->state != OPENED)
3099 	return;
3100 
3101     lcp_magic = lcp_gotoptions[f->unit].magicnumber;
3102     pktp = pkt;
3103     PUTLONG(lcp_magic, pktp);
3104     PUTLONG(time_remaining, pktp);
3105     fsm_sdata(f, CODE_TIMEREMAIN, ++f->id, pkt, pktp - pkt);
3106 }
3107 
3108 /*ARGSUSED*/
3109 static void
3110 lcp_received_timeremain(f, id, inp, len)
3111     fsm *f;
3112     int id;
3113     u_char *inp;
3114     int len;
3115 {
3116     u_int32_t magic;
3117     u_int32_t time_remaining;
3118 
3119     /* Check the magic number - don't count replies from ourselves. */
3120     if (len < 8) {
3121 	dbglog("%s: received short Time-Remain; %d < 8", len);
3122 	return;
3123     }
3124     GETLONG(magic, inp);
3125     if (lcp_gotoptions[f->unit].neg_magicnumber && f->state == OPENED &&
3126 	magic == lcp_gotoptions[f->unit].magicnumber) {
3127 	warn("appear to have received our own Time-Remain!");
3128 	return;
3129     }
3130     GETLONG(time_remaining, inp);
3131     if (len > 8) {
3132 	notice("%d seconds remain: \"%.*s\"", time_remaining,
3133 	    len-8, inp);
3134     } else {
3135 	notice("Time Remaining: %d seconds", time_remaining);
3136     }
3137 }
3138 
3139 /*
3140  * lcp_timeremaining - timeout handler which sends LCP Time-Remaining
3141  * packet.
3142  */
3143 static void
3144 lcp_timeremaining(arg)
3145     void *arg;
3146 {
3147     struct lcp_timer *lt = (struct lcp_timer *)arg;
3148     u_int32_t time_remaining;
3149     int unit;
3150 
3151     unit = lt->unit;
3152     time_remaining = lt->tr;
3153     LcpSendTimeRemaining(&lcp_fsm[unit], time_remaining);
3154     free(lt);
3155 }
3156 
3157 /*
3158  * lcp_settimeremaining - set a timeout to send an LCP Time-Remaining
3159  * packet.  The first argument, connecttime, is the time remaining
3160  * at the time this function is called.  The second argument is the
3161  * desired time remaining when the packet should be sent out.
3162  */
3163 void
3164 lcp_settimeremaining(unit, connecttime, time_remaining)
3165     int unit;
3166     u_int32_t connecttime;
3167     u_int32_t time_remaining;
3168 {
3169     struct lcp_timer *lt;
3170 
3171     if (connecttime == time_remaining) {
3172 	LcpSendTimeRemaining(&lcp_fsm[unit], time_remaining);
3173     } else {
3174 	lt = (struct lcp_timer *)malloc(sizeof (struct lcp_timer));
3175 	lt->unit = unit;
3176 	lt->tr = time_remaining;
3177 	TIMEOUT(lcp_timeremaining, (void *)lt, connecttime - time_remaining);
3178     }
3179 }
3180