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