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