]> git.ozlabs.org Git - ppp.git/blob - pppd/lcp.c
incorporate changes from linux port
[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 #ifndef lint
21 static char rcsid[] = "$Id: lcp.c,v 1.5 1994/05/24 11:23:13 paulus Exp $";
22 #endif
23
24 /*
25  * TODO:
26  */
27
28 #include <stdio.h>
29 #include <syslog.h>
30 #include <assert.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35
36 #include <net/if.h>
37 #include <net/if_ppp.h>
38 #include <netinet/in.h>
39
40 #include <string.h>
41
42 #include "pppd.h"
43 #include "ppp.h"
44 #include "fsm.h"
45 #include "lcp.h"
46 #include "magic.h"
47 #include "chap.h"
48 #include "upap.h"
49 #include "ipcp.h"
50
51 /* global vars */
52 fsm lcp_fsm[NPPP];                      /* LCP fsm structure (global)*/
53 lcp_options lcp_wantoptions[NPPP];      /* Options that we want to request */
54 lcp_options lcp_gotoptions[NPPP];       /* Options that peer ack'd */
55 lcp_options lcp_allowoptions[NPPP];     /* Options we allow peer to request */
56 lcp_options lcp_hisoptions[NPPP];       /* Options that we ack'd */
57 u_long xmit_accm[NPPP][8];              /* extended transmit ACCM */
58
59 static u_long lcp_echos_pending = 0;    /* Number of outstanding echo msgs */
60 static u_long lcp_echo_number   = 0;    /* ID number of next echo frame */
61 static u_long lcp_echo_timer_running = 0;  /* TRUE if a timer is running */
62
63 u_long lcp_echo_interval = 0;
64 u_long lcp_echo_fails = 0;
65
66 /*
67  * Callbacks for fsm code.  (CI = Configuration Information)
68  */
69 static void lcp_resetci __ARGS((fsm *));        /* Reset our CI */
70 static int  lcp_cilen __ARGS((fsm *));          /* Return length of our CI */
71 static void lcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI to pkt */
72 static int  lcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */
73 static int  lcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */
74 static int  lcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */
75 static int  lcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv peer CI */
76 static void lcp_up __ARGS((fsm *));             /* We're UP */
77 static void lcp_down __ARGS((fsm *));           /* We're DOWN */
78 static void lcp_starting __ARGS((fsm *));       /* We need lower layer up */
79 static void lcp_finished __ARGS((fsm *));       /* We need lower layer down */
80 static int  lcp_extcode __ARGS((fsm *, int, int, u_char *, int));
81 static void lcp_rprotrej __ARGS((fsm *, u_char *, int));
82
83 /*
84  * routines to send LCP echos to peer
85  */
86
87 static void lcp_echo_lowerup __ARGS((int));
88 static void lcp_echo_lowerdown __ARGS((int));
89 static void LcpEchoTimeout __ARGS((caddr_t));
90 static void lcp_received_echo_reply __ARGS((fsm *, int, u_char *, int));
91 static void LcpSendEchoRequest __ARGS((fsm *));
92 static void LcpLinkFailure __ARGS((fsm *));
93
94 static fsm_callbacks lcp_callbacks = {  /* LCP callback routines */
95     lcp_resetci,                /* Reset our Configuration Information */
96     lcp_cilen,                  /* Length of our Configuration Information */
97     lcp_addci,                  /* Add our Configuration Information */
98     lcp_ackci,                  /* ACK our Configuration Information */
99     lcp_nakci,                  /* NAK our Configuration Information */
100     lcp_rejci,                  /* Reject our Configuration Information */
101     lcp_reqci,                  /* Request peer's Configuration Information */
102     lcp_up,                     /* Called when fsm reaches OPENED state */
103     lcp_down,                   /* Called when fsm leaves OPENED state */
104     lcp_starting,               /* Called when we want the lower layer up */
105     lcp_finished,               /* Called when we want the lower layer down */
106     NULL,                       /* Called when Protocol-Reject received */
107     NULL,                       /* Retransmission is necessary */
108     lcp_extcode,                /* Called to handle LCP-specific codes */
109     "LCP"                       /* String name of protocol */
110 };
111
112 int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */
113
114 /*
115  * Length of each type of configuration option (in octets)
116  */
117 #define CILEN_VOID      2
118 #define CILEN_SHORT     4       /* CILEN_VOID + sizeof(short) */
119 #define CILEN_CHAP      5       /* CILEN_VOID + sizeof(short) + 1 */
120 #define CILEN_LONG      6       /* CILEN_VOID + sizeof(long) */
121 #define CILEN_LQR       8       /* CILEN_VOID + sizeof(short) + sizeof(long) */
122
123 #define CODENAME(x)     ((x) == CONFACK ? "ACK" : \
124                          (x) == CONFNAK ? "NAK" : "REJ")
125
126
127 /*
128  * lcp_init - Initialize LCP.
129  */
130 void
131 lcp_init(unit)
132     int unit;
133 {
134     fsm *f = &lcp_fsm[unit];
135     lcp_options *wo = &lcp_wantoptions[unit];
136     lcp_options *ao = &lcp_allowoptions[unit];
137
138     f->unit = unit;
139     f->protocol = LCP;
140     f->callbacks = &lcp_callbacks;
141
142     fsm_init(f);
143
144     wo->passive = 0;
145     wo->silent = 0;
146     wo->restart = 0;                    /* Set to 1 in kernels or multi-line
147                                            implementations */
148     wo->neg_mru = 1;
149     wo->mru = DEFMRU;
150     wo->neg_asyncmap = 0;
151     wo->asyncmap = 0;
152     wo->neg_chap = 0;                   /* Set to 1 on server */
153     wo->neg_upap = 0;                   /* Set to 1 on server */
154     wo->chap_mdtype = CHAP_DIGEST_MD5;
155     wo->neg_magicnumber = 1;
156     wo->neg_pcompression = 1;
157     wo->neg_accompression = 1;
158     wo->neg_lqr = 0;                    /* no LQR implementation yet */
159
160     ao->neg_mru = 1;
161     ao->mru = MAXMRU;
162     ao->neg_asyncmap = 1;
163     ao->asyncmap = 0;
164     ao->neg_chap = 1;
165     ao->chap_mdtype = CHAP_DIGEST_MD5;
166     ao->neg_upap = 1;
167     ao->neg_magicnumber = 1;
168     ao->neg_pcompression = 1;
169     ao->neg_accompression = 1;
170     ao->neg_lqr = 0;                    /* no LQR implementation yet */
171
172     memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
173     xmit_accm[unit][3] = 0x60000000;
174 }
175
176
177 /*
178  * lcp_open - LCP is allowed to come up.
179  */
180 void
181 lcp_open(unit)
182     int unit;
183 {
184     fsm *f = &lcp_fsm[unit];
185     lcp_options *wo = &lcp_wantoptions[unit];
186
187     f->flags = 0;
188     if (wo->passive)
189         f->flags |= OPT_PASSIVE;
190     if (wo->silent)
191         f->flags |= OPT_SILENT;
192     fsm_open(f);
193 }
194
195
196 /*
197  * lcp_close - Take LCP down.
198  */
199 void
200 lcp_close(unit)
201     int unit;
202 {
203     fsm *f = &lcp_fsm[unit];
204
205     if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
206         /*
207          * This action is not strictly according to the FSM in RFC1548,
208          * but it does mean that the program terminates if you do a
209          * lcp_close(0) in passive/silent mode when a connection hasn't
210          * been established.
211          */
212         f->state = CLOSED;
213         lcp_finished(f);
214
215     } else
216         fsm_close(&lcp_fsm[unit]);
217 }
218
219
220 /*
221  * lcp_lowerup - The lower layer is up.
222  */
223 void
224 lcp_lowerup(unit)
225     int unit;
226 {
227     sifdown(unit);
228     ppp_set_xaccm(unit, xmit_accm[unit]);
229     ppp_send_config(unit, MTU, 0xffffffff, 0, 0);
230     ppp_recv_config(unit, MTU, 0x00000000, 0, 0);
231     peer_mru[unit] = MTU;
232     lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
233
234     fsm_lowerup(&lcp_fsm[unit]);
235 }
236
237
238 /*
239  * lcp_lowerdown - The lower layer is down.
240  */
241 void
242 lcp_lowerdown(unit)
243     int unit;
244 {
245     fsm_lowerdown(&lcp_fsm[unit]);
246 }
247
248
249 /*
250  * lcp_input - Input LCP packet.
251  */
252 void
253 lcp_input(unit, p, len)
254     int unit;
255     u_char *p;
256     int len;
257 {
258     fsm_input(&lcp_fsm[unit], p, len);
259 }
260
261
262 /*
263  * lcp_extcode - Handle a LCP-specific code.
264  */
265 static int
266 lcp_extcode(f, code, id, inp, len)
267     fsm *f;
268     int code, id;
269     u_char *inp;
270     int len;
271 {
272     u_char *magp;
273
274     switch( code ){
275     case PROTREJ:
276         lcp_rprotrej(f, inp, len);
277         break;
278     
279     case ECHOREQ:
280         if (f->state != OPENED)
281             break;
282         LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id));
283         magp = inp;
284         PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
285         if (len < CILEN_LONG)
286             len = CILEN_LONG;
287         fsm_sdata(f, ECHOREP, id, inp, len);
288         break;
289     
290     case ECHOREP:
291         lcp_received_echo_reply(f, id, inp, len);
292         break;
293
294     case DISCREQ:
295         break;
296
297     default:
298         return 0;
299     }
300     return 1;
301 }
302
303     
304 /*
305  * lcp_rprotrej - Receive an Protocol-Reject.
306  *
307  * Figure out which protocol is rejected and inform it.
308  */
309 static void
310 lcp_rprotrej(f, inp, len)
311     fsm *f;
312     u_char *inp;
313     int len;
314 {
315     u_short prot;
316
317     LCPDEBUG((LOG_INFO, "lcp_rprotrej."));
318
319     if (len < sizeof (u_short)) {
320         LCPDEBUG((LOG_INFO,
321                   "lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
322         return;
323     }
324
325     GETSHORT(prot, inp);
326
327     LCPDEBUG((LOG_INFO,
328               "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!",
329               prot));
330
331     /*
332      * Protocol-Reject packets received in any state other than the LCP
333      * OPENED state SHOULD be silently discarded.
334      */
335     if( f->state != OPENED ){
336         LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d",
337                   f->state));
338         return;
339     }
340
341     DEMUXPROTREJ(f->unit, prot);        /* Inform protocol */
342 }
343
344
345 /*
346  * lcp_protrej - A Protocol-Reject was received.
347  */
348 /*ARGSUSED*/
349 void
350 lcp_protrej(unit)
351     int unit;
352 {
353     /*
354      * Can't reject LCP!
355      */
356     LCPDEBUG((LOG_WARNING,
357               "lcp_protrej: Received Protocol-Reject for LCP!"));
358     fsm_protreject(&lcp_fsm[unit]);
359 }
360
361
362 /*
363  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
364  */
365 void
366 lcp_sprotrej(unit, p, len)
367     int unit;
368     u_char *p;
369     int len;
370 {
371     /*
372      * Send back the protocol and the information field of the
373      * rejected packet.  We only get here if LCP is in the OPENED state.
374      */
375     p += 2;
376     len -= 2;
377
378     fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
379               p, len);
380 }
381
382
383 /*
384  * lcp_resetci - Reset our CI.
385  */
386 static void
387   lcp_resetci(f)
388 fsm *f;
389 {
390     lcp_wantoptions[f->unit].magicnumber = magic();
391     lcp_wantoptions[f->unit].numloops = 0;
392     lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
393     peer_mru[f->unit] = MTU;
394 }
395
396
397 /*
398  * lcp_cilen - Return length of our CI.
399  */
400 static int
401 lcp_cilen(f)
402     fsm *f;
403 {
404     lcp_options *go = &lcp_gotoptions[f->unit];
405
406 #define LENCIVOID(neg)  (neg ? CILEN_VOID : 0)
407 #define LENCICHAP(neg)  (neg ? CILEN_CHAP : 0)
408 #define LENCISHORT(neg) (neg ? CILEN_SHORT : 0)
409 #define LENCILONG(neg)  (neg ? CILEN_LONG : 0)
410 #define LENCILQR(neg)   (neg ? CILEN_LQR: 0)
411     /*
412      * NB: we only ask for one of CHAP and UPAP, even if we will
413      * accept either.
414      */
415     return (LENCISHORT(go->neg_mru) +
416             LENCILONG(go->neg_asyncmap) +
417             LENCICHAP(go->neg_chap) +
418             LENCISHORT(!go->neg_chap && go->neg_upap) +
419             LENCILQR(go->neg_lqr) +
420             LENCILONG(go->neg_magicnumber) +
421             LENCIVOID(go->neg_pcompression) +
422             LENCIVOID(go->neg_accompression));
423 }
424
425
426 /*
427  * lcp_addci - Add our desired CIs to a packet.
428  */
429 static void
430 lcp_addci(f, ucp, lenp)
431     fsm *f;
432     u_char *ucp;
433     int *lenp;
434 {
435     lcp_options *go = &lcp_gotoptions[f->unit];
436     u_char *start_ucp = ucp;
437
438 #define ADDCIVOID(opt, neg) \
439     if (neg) { \
440         PUTCHAR(opt, ucp); \
441         PUTCHAR(CILEN_VOID, ucp); \
442     }
443 #define ADDCISHORT(opt, neg, val) \
444     if (neg) { \
445         PUTCHAR(opt, ucp); \
446         PUTCHAR(CILEN_SHORT, ucp); \
447         PUTSHORT(val, ucp); \
448     }
449 #define ADDCICHAP(opt, neg, val, digest) \
450     if (neg) { \
451         PUTCHAR(opt, ucp); \
452         PUTCHAR(CILEN_CHAP, ucp); \
453         PUTSHORT(val, ucp); \
454         PUTCHAR(digest, ucp); \
455     }
456 #define ADDCILONG(opt, neg, val) \
457     if (neg) { \
458         PUTCHAR(opt, ucp); \
459         PUTCHAR(CILEN_LONG, ucp); \
460         PUTLONG(val, ucp); \
461     }
462 #define ADDCILQR(opt, neg, val) \
463     if (neg) { \
464         PUTCHAR(opt, ucp); \
465         PUTCHAR(CILEN_LQR, ucp); \
466         PUTSHORT(LQR, ucp); \
467         PUTLONG(val, ucp); \
468     }
469
470     ADDCISHORT(CI_MRU, go->neg_mru, go->mru);
471     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
472     ADDCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype);
473     ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP);
474     ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
475     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
476     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
477     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
478
479     if (ucp - start_ucp != *lenp) {
480         /* this should never happen, because peer_mtu should be 1500 */
481         syslog(LOG_ERR, "Bug in lcp_addci: wrong length");
482     }
483 }
484
485
486 /*
487  * lcp_ackci - Ack our CIs.
488  * This should not modify any state if the Ack is bad.
489  *
490  * Returns:
491  *      0 - Ack was bad.
492  *      1 - Ack was good.
493  */
494 static int
495 lcp_ackci(f, p, len)
496     fsm *f;
497     u_char *p;
498     int len;
499 {
500     lcp_options *go = &lcp_gotoptions[f->unit];
501     u_char cilen, citype, cichar;
502     u_short cishort;
503     u_long cilong;
504
505     /*
506      * CIs must be in exactly the same order that we sent.
507      * Check packet length and CI length at each step.
508      * If we find any deviations, then this packet is bad.
509      */
510 #define ACKCIVOID(opt, neg) \
511     if (neg) { \
512         if ((len -= CILEN_VOID) < 0) \
513             goto bad; \
514         GETCHAR(citype, p); \
515         GETCHAR(cilen, p); \
516         if (cilen != CILEN_VOID || \
517             citype != opt) \
518             goto bad; \
519     }
520 #define ACKCISHORT(opt, neg, val) \
521     if (neg) { \
522         if ((len -= CILEN_SHORT) < 0) \
523             goto bad; \
524         GETCHAR(citype, p); \
525         GETCHAR(cilen, p); \
526         if (cilen != CILEN_SHORT || \
527             citype != opt) \
528             goto bad; \
529         GETSHORT(cishort, p); \
530         if (cishort != val) \
531             goto bad; \
532     }
533 #define ACKCICHAP(opt, neg, val, digest) \
534     if (neg) { \
535         if ((len -= CILEN_CHAP) < 0) \
536             goto bad; \
537         GETCHAR(citype, p); \
538         GETCHAR(cilen, p); \
539         if (cilen != CILEN_CHAP || \
540             citype != opt) \
541             goto bad; \
542         GETSHORT(cishort, p); \
543         if (cishort != val) \
544             goto bad; \
545         GETCHAR(cichar, p); \
546         if (cichar != digest) \
547           goto bad; \
548     }
549 #define ACKCILONG(opt, neg, val) \
550     if (neg) { \
551         if ((len -= CILEN_LONG) < 0) \
552             goto bad; \
553         GETCHAR(citype, p); \
554         GETCHAR(cilen, p); \
555         if (cilen != CILEN_LONG || \
556             citype != opt) \
557             goto bad; \
558         GETLONG(cilong, p); \
559         if (cilong != val) \
560             goto bad; \
561     }
562 #define ACKCILQR(opt, neg, val) \
563     if (neg) { \
564         if ((len -= CILEN_LQR) < 0) \
565             goto bad; \
566         GETCHAR(citype, p); \
567         GETCHAR(cilen, p); \
568         if (cilen != CILEN_LQR || \
569             citype != opt) \
570             goto bad; \
571         GETSHORT(cishort, p); \
572         if (cishort != LQR) \
573             goto bad; \
574         GETLONG(cilong, p); \
575         if (cilong != val) \
576           goto bad; \
577     }
578
579     ACKCISHORT(CI_MRU, go->neg_mru, go->mru);
580     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
581     ACKCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype);
582     ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP);
583     ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
584     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
585     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
586     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
587
588     /*
589      * If there are any remaining CIs, then this packet is bad.
590      */
591     if (len != 0)
592         goto bad;
593     return (1);
594 bad:
595     LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!"));
596     return (0);
597 }
598
599
600 /*
601  * lcp_nakci - Peer has sent a NAK for some of our CIs.
602  * This should not modify any state if the Nak is bad
603  * or if LCP is in the OPENED state.
604  *
605  * Returns:
606  *      0 - Nak was bad.
607  *      1 - Nak was good.
608  */
609 static int
610 lcp_nakci(f, p, len)
611     fsm *f;
612     u_char *p;
613     int len;
614 {
615     lcp_options *go = &lcp_gotoptions[f->unit];
616     lcp_options *wo = &lcp_wantoptions[f->unit];
617     u_char cilen, citype, cichar, *next;
618     u_short cishort;
619     u_long cilong;
620     lcp_options no;             /* options we've seen Naks for */
621     lcp_options try;            /* options to request next time */
622     int looped_back = 0;
623
624     BZERO(&no, sizeof(no));
625     try = *go;
626
627     /*
628      * Any Nak'd CIs must be in exactly the same order that we sent.
629      * Check packet length and CI length at each step.
630      * If we find any deviations, then this packet is bad.
631      */
632 #define NAKCIVOID(opt, neg, code) \
633     if (go->neg && \
634         len >= CILEN_VOID && \
635         p[1] == CILEN_VOID && \
636         p[0] == opt) { \
637         len -= CILEN_VOID; \
638         INCPTR(CILEN_VOID, p); \
639         no.neg = 1; \
640         code \
641     }
642 #define NAKCICHAP(opt, neg, code) \
643     if (go->neg && \
644         len >= CILEN_CHAP && \
645         p[1] == CILEN_CHAP && \
646         p[0] == opt) { \
647         len -= CILEN_CHAP; \
648         INCPTR(2, p); \
649         GETSHORT(cishort, p); \
650         GETCHAR(cichar, p); \
651         no.neg = 1; \
652         code \
653     }
654 #define NAKCISHORT(opt, neg, code) \
655     if (go->neg && \
656         len >= CILEN_SHORT && \
657         p[1] == CILEN_SHORT && \
658         p[0] == opt) { \
659         len -= CILEN_SHORT; \
660         INCPTR(2, p); \
661         GETSHORT(cishort, p); \
662         no.neg = 1; \
663         code \
664     }
665 #define NAKCILONG(opt, neg, code) \
666     if (go->neg && \
667         len >= CILEN_LONG && \
668         p[1] == CILEN_LONG && \
669         p[0] == opt) { \
670         len -= CILEN_LONG; \
671         INCPTR(2, p); \
672         GETLONG(cilong, p); \
673         no.neg = 1; \
674         code \
675     }
676 #define NAKCILQR(opt, neg, code) \
677     if (go->neg && \
678         len >= CILEN_LQR && \
679         p[1] == CILEN_LQR && \
680         p[0] == opt) { \
681         len -= CILEN_LQR; \
682         INCPTR(2, p); \
683         GETSHORT(cishort, p); \
684         GETLONG(cilong, p); \
685         no.neg = 1; \
686         code \
687     }
688
689     /*
690      * We don't care if they want to send us smaller packets than
691      * we want.  Therefore, accept any MRU less than what we asked for,
692      * but then ignore the new value when setting the MRU in the kernel.
693      * If they send us a bigger MRU than what we asked, accept it, up to
694      * the limit of the default MRU we'd get if we didn't negotiate.
695      */
696     NAKCISHORT(CI_MRU, neg_mru,
697                if (cishort <= wo->mru || cishort < DEFMRU)
698                    try.mru = cishort;
699                );
700     /*
701      * Add any characters they want to our (receive-side) asyncmap.
702      */
703     NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
704               try.asyncmap = go->asyncmap | cilong;
705               );
706     /*
707      * If they can't cope with our CHAP hash algorithm, we'll have
708      * to stop asking for CHAP.  We haven't got any other algorithm.
709      */
710     NAKCICHAP(CI_AUTHTYPE, neg_chap,
711               try.neg_chap = 0;
712               );
713     /*
714      * Peer shouldn't send Nak for UPAP, protocol compression or
715      * address/control compression requests; they should send
716      * a Reject instead.  If they send a Nak, treat it as a Reject.
717      */
718     if (!go->neg_chap ){
719         NAKCISHORT(CI_AUTHTYPE, neg_upap,
720                    try.neg_upap = 0;
721                    );
722     }
723     /*
724      * If they can't cope with our link quality protocol, we'll have
725      * to stop asking for LQR.  We haven't got any other protocol.
726      * If they Nak the reporting period, take their value XXX ?
727      */
728     NAKCILQR(CI_QUALITY, neg_lqr,
729              if (cishort != LQR)
730                  try.neg_lqr = 0;
731              else
732                  try.lqr_period = cilong;
733              );
734     /*
735      * Check for a looped-back line.
736      */
737     NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
738               try.magicnumber = magic();
739               ++try.numloops;
740               looped_back = 1;
741               );
742
743     NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
744               try.neg_pcompression = 0;
745               );
746     NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
747               try.neg_accompression = 0;
748               );
749
750     /*
751      * There may be remaining CIs, if the peer is requesting negotiation
752      * on an option that we didn't include in our request packet.
753      * If we see an option that we requested, or one we've already seen
754      * in this packet, then this packet is bad.
755      * If we wanted to respond by starting to negotiate on the requested
756      * option(s), we could, but we don't, because except for the
757      * authentication type and quality protocol, if we are not negotiating
758      * an option, it is because we were told not to.
759      * For the authentication type, the Nak from the peer means
760      * `let me authenticate myself with you' which is a bit pointless.
761      * For the quality protocol, the Nak means `ask me to send you quality
762      * reports', but if we didn't ask for them, we don't want them.
763      */
764     while (len > CILEN_VOID) {
765         GETCHAR(citype, p);
766         GETCHAR(cilen, p);
767         if( (len -= cilen) < 0 )
768             goto bad;
769         next = p + cilen - 2;
770
771         switch (citype) {
772         case CI_MRU:
773             if (go->neg_mru || no.neg_mru || cilen != CILEN_SHORT)
774                 goto bad;
775             break;
776         case CI_ASYNCMAP:
777             if (go->neg_asyncmap || no.neg_asyncmap || cilen != CILEN_LONG)
778                 goto bad;
779             break;
780         case CI_AUTHTYPE:
781             if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
782                 goto bad;
783             break;
784         case CI_MAGICNUMBER:
785             if (go->neg_magicnumber || no.neg_magicnumber ||
786                 cilen != CILEN_LONG)
787                 goto bad;
788             break;
789         case CI_PCOMPRESSION:
790             if (go->neg_pcompression || no.neg_pcompression
791                 || cilen != CILEN_VOID)
792                 goto bad;
793             break;
794         case CI_ACCOMPRESSION:
795             if (go->neg_accompression || no.neg_accompression
796                 || cilen != CILEN_VOID)
797                 goto bad;
798             break;
799         case CI_QUALITY:
800             if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
801                 goto bad;
802             break;
803         default:
804             goto bad;
805         }
806         p = next;
807     }
808
809     /* If there is still anything left, this packet is bad. */
810     if (len != 0)
811         goto bad;
812
813     /*
814      * OK, the Nak is good.  Now we can update state.
815      */
816     if (f->state != OPENED) {
817         *go = try;
818         if (looped_back && try.numloops % lcp_warnloops == 0)
819             LCPDEBUG((LOG_INFO, "The line appears to be looped back."));
820     }
821
822     return 1;
823
824 bad:
825     LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!"));
826     return 0;
827 }
828
829
830 /*
831  * lcp_rejci - Peer has Rejected some of our CIs.
832  * This should not modify any state if the Reject is bad
833  * or if LCP is in the OPENED state.
834  *
835  * Returns:
836  *      0 - Reject was bad.
837  *      1 - Reject was good.
838  */
839 static int
840 lcp_rejci(f, p, len)
841     fsm *f;
842     u_char *p;
843     int len;
844 {
845     lcp_options *go = &lcp_gotoptions[f->unit];
846     u_char cichar;
847     u_short cishort;
848     u_long cilong;
849     u_char *start = p;
850     int plen = len;
851     lcp_options try;            /* options to request next time */
852
853     try = *go;
854
855     /*
856      * Any Rejected CIs must be in exactly the same order that we sent.
857      * Check packet length and CI length at each step.
858      * If we find any deviations, then this packet is bad.
859      */
860 #define REJCIVOID(opt, neg) \
861     if (go->neg && \
862         len >= CILEN_VOID && \
863         p[1] == CILEN_VOID && \
864         p[0] == opt) { \
865         len -= CILEN_VOID; \
866         INCPTR(CILEN_VOID, p); \
867         try.neg = 0; \
868         LCPDEBUG((LOG_INFO, "lcp_rejci rejected void opt %d", opt)); \
869     }
870 #define REJCISHORT(opt, neg, val) \
871     if (go->neg && \
872         len >= CILEN_SHORT && \
873         p[1] == CILEN_SHORT && \
874         p[0] == opt) { \
875         len -= CILEN_SHORT; \
876         INCPTR(2, p); \
877         GETSHORT(cishort, p); \
878         /* Check rejected value. */ \
879         if (cishort != val) \
880             goto bad; \
881         try.neg = 0; \
882         LCPDEBUG((LOG_INFO,"lcp_rejci rejected short opt %d", opt)); \
883     }
884 #define REJCICHAP(opt, neg, val, digest) \
885     if (go->neg && \
886         len >= CILEN_CHAP && \
887         p[1] == CILEN_CHAP && \
888         p[0] == opt) { \
889         len -= CILEN_CHAP; \
890         INCPTR(2, p); \
891         GETSHORT(cishort, p); \
892         GETCHAR(cichar, p); \
893         /* Check rejected value. */ \
894         if (cishort != val || cichar != digest) \
895             goto bad; \
896         try.neg = 0; \
897         LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \
898     }
899 #define REJCILONG(opt, neg, val) \
900     if (go->neg && \
901         len >= CILEN_LONG && \
902         p[1] == CILEN_LONG && \
903         p[0] == opt) { \
904         len -= CILEN_LONG; \
905         INCPTR(2, p); \
906         GETLONG(cilong, p); \
907         /* Check rejected value. */ \
908         if (cilong != val) \
909             goto bad; \
910         try.neg = 0; \
911         LCPDEBUG((LOG_INFO,"lcp_rejci rejected long opt %d", opt)); \
912     }
913 #define REJCILQR(opt, neg, val) \
914     if (go->neg && \
915         len >= CILEN_LQR && \
916         p[1] == CILEN_LQR && \
917         p[0] == opt) { \
918         len -= CILEN_LQR; \
919         INCPTR(2, p); \
920         GETSHORT(cishort, p); \
921         GETLONG(cilong, p); \
922         /* Check rejected value. */ \
923         if (cishort != LQR || cilong != val) \
924             goto bad; \
925         try.neg = 0; \
926         LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
927     }
928
929     REJCISHORT(CI_MRU, neg_mru, go->mru);
930     REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
931     REJCICHAP(CI_AUTHTYPE, neg_chap, CHAP, go->chap_mdtype);
932     if (!go->neg_chap) {
933         REJCISHORT(CI_AUTHTYPE, neg_upap, UPAP);
934     }
935     REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
936     REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
937     REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
938     REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
939
940     /*
941      * If there are any remaining CIs, then this packet is bad.
942      */
943     if (len != 0)
944         goto bad;
945     /*
946      * Now we can update state.
947      */
948     if (f->state != OPENED)
949         *go = try;
950     return 1;
951
952 bad:
953     LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!"));
954     LCPDEBUG((LOG_WARNING, "lcp_rejci: plen %d len %d off %d",
955               plen, len, p - start));
956     return 0;
957 }
958
959
960 /*
961  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
962  *
963  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
964  * appropriately.  If reject_if_disagree is non-zero, doesn't return
965  * CONFNAK; returns CONFREJ if it can't return CONFACK.
966  */
967 static int
968 lcp_reqci(f, inp, lenp, reject_if_disagree)
969     fsm *f;
970     u_char *inp;                /* Requested CIs */
971     int *lenp;                  /* Length of requested CIs */
972     int reject_if_disagree;
973 {
974     lcp_options *go = &lcp_gotoptions[f->unit];
975     lcp_options *ho = &lcp_hisoptions[f->unit];
976     lcp_options *ao = &lcp_allowoptions[f->unit];
977     u_char *cip, *next;         /* Pointer to current and next CIs */
978     u_char cilen, citype, cichar;/* Parsed len, type, char value */
979     u_short cishort;            /* Parsed short value */
980     u_long cilong;              /* Parse long value */
981     int rc = CONFACK;           /* Final packet return code */
982     int orc;                    /* Individual option return code */
983     u_char *p;                  /* Pointer to next char to parse */
984     u_char *ucp = inp;          /* Pointer to current output char */
985     int l = *lenp;              /* Length left */
986
987     /*
988      * Reset all his options.
989      */
990     BZERO(ho, sizeof(*ho));
991
992     /*
993      * Process all his options.
994      */
995     next = inp;
996     while (l) {
997         orc = CONFACK;                  /* Assume success */
998         cip = p = next;                 /* Remember begining of CI */
999         if (l < 2 ||                    /* Not enough data for CI header or */
1000             p[1] < 2 ||                 /*  CI length too small or */
1001             p[1] > l) {                 /*  CI length too big? */
1002             LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!"));
1003             orc = CONFREJ;              /* Reject bad CI */
1004             cilen = l;                  /* Reject till end of packet */
1005             l = 0;                      /* Don't loop again */
1006             goto endswitch;
1007         }
1008         GETCHAR(citype, p);             /* Parse CI type */
1009         GETCHAR(cilen, p);              /* Parse CI length */
1010         l -= cilen;                     /* Adjust remaining length */
1011         next += cilen;                  /* Step to next CI */
1012
1013         switch (citype) {               /* Check CI type */
1014         case CI_MRU:
1015             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MRU"));
1016             if (!ao->neg_mru ||         /* Allow option? */
1017                 cilen != CILEN_SHORT) { /* Check CI length */
1018                 orc = CONFREJ;          /* Reject CI */
1019                 break;
1020             }
1021             GETSHORT(cishort, p);       /* Parse MRU */
1022             LCPDEBUG((LOG_INFO, "(%d)", cishort));
1023
1024             /*
1025              * He must be able to receive at least our minimum.
1026              * No need to check a maximum.  If he sends a large number,
1027              * we'll just ignore it.
1028              */
1029             if (cishort < MINMRU) {
1030                 orc = CONFNAK;          /* Nak CI */
1031                 if( !reject_if_disagree ){
1032                     DECPTR(sizeof (short), p);  /* Backup */
1033                     PUTSHORT(MINMRU, p);        /* Give him a hint */
1034                 }
1035                 break;
1036             }
1037             ho->neg_mru = 1;            /* Remember he sent MRU */
1038             ho->mru = cishort;          /* And remember value */
1039             break;
1040
1041         case CI_ASYNCMAP:
1042             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ASYNCMAP"));
1043             if (!ao->neg_asyncmap ||
1044                 cilen != CILEN_LONG) {
1045                 orc = CONFREJ;
1046                 break;
1047             }
1048             GETLONG(cilong, p);
1049             LCPDEBUG((LOG_INFO, "(%lx)", cilong));
1050
1051             /*
1052              * Asyncmap must have set at least the bits
1053              * which are set in lcp_allowoptions[unit].asyncmap.
1054              */
1055             if ((ao->asyncmap & ~cilong) != 0) {
1056                 orc = CONFNAK;
1057                 if( !reject_if_disagree ){
1058                     DECPTR(sizeof (long), p);
1059                     PUTLONG(ao->asyncmap | cilong, p);
1060                 }
1061                 break;
1062             }
1063             ho->neg_asyncmap = 1;
1064             ho->asyncmap = cilong;
1065             break;
1066
1067         case CI_AUTHTYPE:
1068             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE"));
1069             if (cilen < CILEN_SHORT ||
1070                 !(ao->neg_upap || ao->neg_chap)) {
1071                 orc = CONFREJ;
1072                 break;
1073             }
1074             GETSHORT(cishort, p);
1075             LCPDEBUG((LOG_INFO, "(%x)", cishort));
1076
1077             /*
1078              * Authtype must be UPAP or CHAP.
1079              *
1080              * Note: if both ao->neg_upap and ao->neg_chap are set,
1081              * and the peer sends a Configure-Request with two
1082              * authenticate-protocol requests, one for CHAP and one
1083              * for UPAP, then we will reject the second request.
1084              * Whether we end up doing CHAP or UPAP depends then on
1085              * the ordering of the CIs in the peer's Configure-Request.
1086              */
1087
1088             if (cishort == UPAP) {
1089                 if (!ao->neg_upap ||    /* we don't want to do PAP */
1090                     ho->neg_chap ||     /* or we've already accepted CHAP */
1091                     cilen != CILEN_SHORT) {
1092                     LCPDEBUG((LOG_WARNING,
1093                               "lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1094                     orc = CONFREJ;
1095                     break;
1096                 }
1097                 ho->neg_upap = 1;
1098                 break;
1099             }
1100             if (cishort == CHAP) {
1101                 if (!ao->neg_chap ||    /* we don't want to do CHAP */
1102                     ho->neg_upap ||     /* or we've already accepted UPAP */
1103                     cilen != CILEN_CHAP) {
1104                     LCPDEBUG((LOG_INFO,
1105                               "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
1106                     orc = CONFREJ;
1107                     break;
1108                 }
1109                 GETCHAR(cichar, p);     /* get digest type*/
1110                 if (cichar != ao->chap_mdtype) {
1111                     orc = CONFNAK;
1112                     if( !reject_if_disagree ){
1113                         DECPTR(sizeof (u_char), p);
1114                         PUTCHAR(ao->chap_mdtype, p);
1115                     }
1116                     break;
1117                 }
1118                 ho->chap_mdtype = cichar; /* save md type */
1119                 ho->neg_chap = 1;
1120                 break;
1121             }
1122
1123             /*
1124              * We don't recognize the protocol they're asking for.
1125              * Reject it.
1126              */
1127             orc = CONFREJ;
1128             break;
1129
1130         case CI_QUALITY:
1131             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY"));
1132             if (!ao->neg_lqr ||
1133                 cilen != CILEN_LQR) {
1134                 orc = CONFREJ;
1135                 break;
1136             }
1137
1138             GETSHORT(cishort, p);
1139             GETLONG(cilong, p);
1140             LCPDEBUG((LOG_INFO, "(%x %lx)", cishort, cilong));
1141             if (cishort != LQR) {
1142                 orc = CONFREJ;
1143                 break;
1144             }
1145
1146             /*
1147              * Check the reporting period.
1148              * XXX When should we Nak this, and what with?
1149              */
1150             break;
1151
1152         case CI_MAGICNUMBER:
1153             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER"));
1154             if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
1155                 cilen != CILEN_LONG) {
1156                 orc = CONFREJ;
1157                 break;
1158             }
1159             GETLONG(cilong, p);
1160             LCPDEBUG((LOG_INFO, "(%lx)", cilong));
1161
1162             /*
1163              * He must have a different magic number.
1164              */
1165             if (go->neg_magicnumber &&
1166                 cilong == go->magicnumber) {
1167                 orc = CONFNAK;
1168                 DECPTR(sizeof (long), p);
1169                 cilong = magic();       /* Don't put magic() inside macro! */
1170                 PUTLONG(cilong, p);
1171                 break;
1172             }
1173             ho->neg_magicnumber = 1;
1174             ho->magicnumber = cilong;
1175             break;
1176
1177
1178         case CI_PCOMPRESSION:
1179             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION"));
1180             if (!ao->neg_pcompression ||
1181                 cilen != CILEN_VOID) {
1182                 orc = CONFREJ;
1183                 break;
1184             }
1185             ho->neg_pcompression = 1;
1186             break;
1187
1188         case CI_ACCOMPRESSION:
1189             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION"));
1190             if (!ao->neg_accompression ||
1191                 cilen != CILEN_VOID) {
1192                 orc = CONFREJ;
1193                 break;
1194             }
1195             ho->neg_accompression = 1;
1196             break;
1197
1198         default:
1199             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d",
1200                       citype));
1201             orc = CONFREJ;
1202             break;
1203         }
1204
1205 endswitch:
1206         LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc)));
1207         if (orc == CONFACK &&           /* Good CI */
1208             rc != CONFACK)              /*  but prior CI wasnt? */
1209             continue;                   /* Don't send this one */
1210
1211         if (orc == CONFNAK) {           /* Nak this CI? */
1212             if (reject_if_disagree)     /* Getting fed up with sending NAKs? */
1213                 orc = CONFREJ;          /* Get tough if so */
1214             else {
1215                 if (rc == CONFREJ)      /* Rejecting prior CI? */
1216                     continue;           /* Don't send this one */
1217                 if (rc == CONFACK) {    /* Ack'd all prior CIs? */
1218                     rc = CONFNAK;       /* Not anymore... */
1219                     ucp = inp;          /* Backup */
1220                 }
1221             }
1222         }
1223         if (orc == CONFREJ &&           /* Reject this CI */
1224             rc != CONFREJ) {            /*  but no prior ones? */
1225             rc = CONFREJ;
1226             ucp = inp;                  /* Backup */
1227         }
1228         if (ucp != cip)                 /* Need to move CI? */
1229             BCOPY(cip, ucp, cilen);     /* Move it */
1230         INCPTR(cilen, ucp);             /* Update output pointer */
1231     }
1232
1233     /*
1234      * If we wanted to send additional NAKs (for unsent CIs), the
1235      * code would go here.  This must be done with care since it might
1236      * require a longer packet than we received.  At present there
1237      * are no cases where we want to ask the peer to negotiate an option.
1238      */
1239
1240     *lenp = ucp - inp;                  /* Compute output length */
1241     LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc)));
1242     return (rc);                        /* Return final code */
1243 }
1244
1245
1246 /*
1247  * lcp_up - LCP has come UP.
1248  *
1249  * Start UPAP, IPCP, etc.
1250  */
1251 static void
1252 lcp_up(f)
1253     fsm *f;
1254 {
1255     lcp_options *wo = &lcp_wantoptions[f->unit];
1256     lcp_options *ho = &lcp_hisoptions[f->unit];
1257     lcp_options *go = &lcp_gotoptions[f->unit];
1258     lcp_options *ao = &lcp_allowoptions[f->unit];
1259
1260     if (!go->neg_magicnumber)
1261         go->magicnumber = 0;
1262     if (!ho->neg_magicnumber)
1263         ho->magicnumber = 0;
1264
1265     /*
1266      * Set our MTU to the smaller of the MTU we wanted and
1267      * the MRU our peer wanted.  If we negotiated an MRU,
1268      * set our MRU to the larger of value we wanted and
1269      * the value we got in the negotiation.
1270      */
1271     ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: MTU)),
1272                     (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
1273                     ho->neg_pcompression, ho->neg_accompression);
1274     ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): MTU),
1275                     (go->neg_asyncmap? go->asyncmap: 0xffffffff),
1276                     go->neg_pcompression, go->neg_accompression);
1277
1278     if (ho->neg_mru)
1279         peer_mru[f->unit] = ho->mru;
1280
1281     ChapLowerUp(f->unit);       /* Enable CHAP */
1282     upap_lowerup(f->unit);      /* Enable UPAP */
1283     ipcp_lowerup(f->unit);      /* Enable IPCP */
1284     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
1285
1286     link_established(f->unit);
1287 }
1288
1289
1290 /*
1291  * lcp_down - LCP has gone DOWN.
1292  *
1293  * Alert other protocols.
1294  */
1295 static void
1296 lcp_down(f)
1297     fsm *f;
1298 {
1299     lcp_echo_lowerdown(f->unit);
1300     ipcp_lowerdown(f->unit);
1301     ChapLowerDown(f->unit);
1302     upap_lowerdown(f->unit);
1303
1304     sifdown(f->unit);
1305     ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0);
1306     ppp_recv_config(f->unit, MTU, 0x00000000, 0, 0);
1307     peer_mru[f->unit] = MTU;
1308
1309     link_down(f->unit);
1310 }
1311
1312
1313 /*
1314  * lcp_starting - LCP needs the lower layer up.
1315  */
1316 static void
1317 lcp_starting(f)
1318     fsm *f;
1319 {
1320     link_required(f->unit);
1321 }
1322
1323
1324 /*
1325  * lcp_finished - LCP has finished with the lower layer.
1326  */
1327 static void
1328 lcp_finished(f)
1329     fsm *f;
1330 {
1331     link_terminated(f->unit);
1332 }
1333
1334
1335 /*
1336  * lcp_printpkt - print the contents of an LCP packet.
1337  */
1338 char *lcp_codenames[] = {
1339     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1340     "TermReq", "TermAck", "CodeRej", "ProtRej",
1341     "EchoReq", "EchoRep", "DiscReq"
1342 };
1343
1344 int
1345 lcp_printpkt(p, plen, printer, arg)
1346     u_char *p;
1347     int plen;
1348     void (*printer) __ARGS((void *, char *, ...));
1349     void *arg;
1350 {
1351     int code, id, len, olen;
1352     u_char *pstart, *optend;
1353     u_short cishort;
1354     u_long cilong;
1355
1356     if (plen < HEADERLEN)
1357         return 0;
1358     pstart = p;
1359     GETCHAR(code, p);
1360     GETCHAR(id, p);
1361     GETSHORT(len, p);
1362     if (len < HEADERLEN || len > plen)
1363         return 0;
1364
1365     if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
1366         printer(arg, " %s", lcp_codenames[code-1]);
1367     else
1368         printer(arg, " code=0x%x", code);
1369     printer(arg, " id=0x%x", id);
1370     len -= HEADERLEN;
1371     switch (code) {
1372     case CONFREQ:
1373     case CONFACK:
1374     case CONFNAK:
1375     case CONFREJ:
1376         /* print option list */
1377         while (len >= 2) {
1378             GETCHAR(code, p);
1379             GETCHAR(olen, p);
1380             p -= 2;
1381             if (olen < 2 || olen > len) {
1382                 break;
1383             }
1384             printer(arg, " <");
1385             len -= olen;
1386             optend = p + olen;
1387             switch (code) {
1388             case CI_MRU:
1389                 if (olen == CILEN_SHORT) {
1390                     p += 2;
1391                     GETSHORT(cishort, p);
1392                     printer(arg, "mru %d", cishort);
1393                 }
1394                 break;
1395             case CI_ASYNCMAP:
1396                 if (olen == CILEN_LONG) {
1397                     p += 2;
1398                     GETLONG(cilong, p);
1399                     printer(arg, "asyncmap 0x%x", cilong);
1400                 }
1401                 break;
1402             case CI_AUTHTYPE:
1403                 if (olen >= CILEN_SHORT) {
1404                     p += 2;
1405                     printer(arg, "auth ");
1406                     GETSHORT(cishort, p);
1407                     switch (cishort) {
1408                     case UPAP:
1409                         printer(arg, "upap");
1410                         break;
1411                     case CHAP:
1412                         printer(arg, "chap");
1413                         break;
1414                     default:
1415                         printer(arg, "0x%x", cishort);
1416                     }
1417                 }
1418                 break;
1419             case CI_QUALITY:
1420                 if (olen >= CILEN_SHORT) {
1421                     p += 2;
1422                     printer(arg, "quality ");
1423                     GETSHORT(cishort, p);
1424                     switch (cishort) {
1425                     case LQR:
1426                         printer(arg, "lqr");
1427                         break;
1428                     default:
1429                         printer(arg, "0x%x", cishort);
1430                     }
1431                 }
1432                 break;
1433             case CI_MAGICNUMBER:
1434                 if (olen == CILEN_LONG) {
1435                     p += 2;
1436                     GETLONG(cilong, p);
1437                     printer(arg, "magic 0x%x", cilong);
1438                 }
1439                 break;
1440             case CI_PCOMPRESSION:
1441                 if (olen == CILEN_VOID) {
1442                     p += 2;
1443                     printer(arg, "pcomp");
1444                 }
1445                 break;
1446             case CI_ACCOMPRESSION:
1447                 if (olen == CILEN_VOID) {
1448                     p += 2;
1449                     printer(arg, "accomp");
1450                 }
1451                 break;
1452             }
1453             while (p < optend) {
1454                 GETCHAR(code, p);
1455                 printer(arg, " %.2x", code);
1456             }
1457             printer(arg, ">");
1458         }
1459         break;
1460     }
1461
1462     /* print the rest of the bytes in the packet */
1463     for (; len > 0; --len) {
1464         GETCHAR(code, p);
1465         printer(arg, " %.2x", code);
1466     }
1467
1468     return p - pstart;
1469 }
1470
1471 /*
1472  * Time to shut down the link because there is nothing out there.
1473  */
1474
1475 static
1476 void LcpLinkFailure (f)
1477     fsm *f;
1478 {
1479     if (f->state == OPENED) {
1480         syslog (LOG_NOTICE, "Excessive lack of response to LCP echo frames.");
1481         lcp_lowerdown(f->unit);         /* Reset connection */
1482     }
1483 }
1484
1485 /*
1486  * Timer expired for the LCP echo requests from this process.
1487  */
1488
1489 static void
1490 LcpEchoCheck (f)
1491     fsm *f;
1492 {
1493     u_long             delta;
1494 #ifdef __linux__
1495     struct ppp_ddinfo  ddinfo;
1496     u_long             latest;
1497 /*
1498  * Read the time since the last packet was received.
1499  */
1500     if (ioctl (fd, PPPIOCGTIME, &ddinfo) < 0) {
1501         syslog (LOG_ERR, "ioctl(PPPIOCGTIME): %m");
1502         die (1);
1503     }
1504 /*
1505  * Choose the most recient frame received. It may be an IP or NON-IP frame.
1506  */
1507     latest = ddinfo.nip_rjiffies < ddinfo.ip_rjiffies ? ddinfo.nip_rjiffies
1508                                                       : ddinfo.ip_rjiffies;
1509 /*
1510  * Compute the time since the last packet was received. If the timer
1511  *  has expired then send the echo request and reset the timer to maximum.
1512  */
1513     delta = (lcp_echo_interval * HZ) - latest;
1514     if (delta < HZ || latest < 0L) {
1515         LcpSendEchoRequest (f);
1516         delta = lcp_echo_interval * HZ;
1517     }
1518     delta /= HZ;
1519
1520 #else /* Other implementations do not have ability to find delta */
1521     LcpSendEchoRequest (f);
1522     delta = lcp_echo_interval;
1523 #endif
1524
1525 /*
1526  * Start the timer for the next interval.
1527  */
1528     assert (lcp_echo_timer_running==0);
1529     TIMEOUT (LcpEchoTimeout, (caddr_t) f, delta);
1530     lcp_echo_timer_running = 1;
1531 }
1532
1533 /*
1534  * LcpEchoTimeout - Timer expired on the LCP echo
1535  */
1536
1537 static void
1538 LcpEchoTimeout (arg)
1539     caddr_t arg;
1540 {
1541     if (lcp_echo_timer_running != 0) {
1542         lcp_echo_timer_running = 0;
1543         LcpEchoCheck ((fsm *) arg);
1544     }
1545 }
1546
1547 /*
1548  * LcpEchoReply - LCP has received a reply to the echo
1549  */
1550
1551 static void
1552 lcp_received_echo_reply (f, id, inp, len)
1553     fsm *f;
1554     int id; u_char *inp; int len;
1555 {
1556     u_long magic;
1557
1558     /* Check the magic number - don't count replies from ourselves. */
1559     if (len < CILEN_LONG)
1560         return;
1561     GETLONG(magic, inp);
1562     if (lcp_gotoptions[f->unit].neg_magicnumber
1563         && magic == lcp_gotoptions[f->unit].magicnumber)
1564         return;
1565
1566     /* Reset the number of outstanding echo frames */
1567     lcp_echos_pending = 0;
1568 }
1569
1570 /*
1571  * LcpSendEchoRequest - Send an echo request frame to the peer
1572  */
1573
1574 static void
1575 LcpSendEchoRequest (f)
1576     fsm *f;
1577 {
1578     u_long lcp_magic;
1579     u_char pkt[4], *pktp;
1580
1581 /*
1582  * Detect the failure of the peer at this point.
1583  */
1584     if (lcp_echo_fails != 0) {
1585         if (lcp_echos_pending++ >= lcp_echo_fails) {
1586             LcpLinkFailure(f);
1587             lcp_echos_pending = 0;
1588         }
1589     }
1590 /*
1591  * Make and send the echo request frame.
1592  */
1593     if (f->state == OPENED) {
1594         lcp_magic = lcp_gotoptions[f->unit].neg_magicnumber
1595                     ? lcp_gotoptions[f->unit].magicnumber
1596                     : 0L;
1597         pktp = pkt;
1598         PUTLONG(lcp_magic, pktp);
1599       
1600         fsm_sdata(f, ECHOREQ,
1601                   lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
1602     }
1603 }
1604
1605 /*
1606  * lcp_echo_lowerup - Start the timer for the LCP frame
1607  */
1608
1609 static void
1610 lcp_echo_lowerup (unit)
1611     int unit;
1612 {
1613     fsm *f = &lcp_fsm[unit];
1614
1615     /* Clear the parameters for generating echo frames */
1616     lcp_echos_pending      = 0;
1617     lcp_echo_number        = 0;
1618     lcp_echo_timer_running = 0;
1619   
1620     /* If a timeout interval is specified then start the timer */
1621     if (lcp_echo_interval != 0)
1622         LcpEchoCheck (f);
1623 }
1624
1625 /*
1626  * lcp_echo_lowerdown - Stop the timer for the LCP frame
1627  */
1628
1629 static void
1630 lcp_echo_lowerdown (unit)
1631     int unit;
1632 {
1633     fsm *f = &lcp_fsm[unit];
1634
1635     if (lcp_echo_timer_running != 0) {
1636         UNTIMEOUT (LcpEchoTimeout, (caddr_t) f);
1637         lcp_echo_timer_running = 0;
1638     }
1639 }