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