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