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