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