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