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