]> git.ozlabs.org Git - ppp.git/blob - pppd/lcp.c
MP-related code should be wrapped within HAVE_MULTILINK pre-processor
[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.54 2000/04/27 03:51:18 masputra 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 #ifdef HAVE_MULTILINK
570     if (noendpoint)
571         ao->neg_endpoint = 0;
572 #endif /* HAVE_MULTILINK */
573     peer_mru[f->unit] = PPP_MRU;
574     auth_reset(f->unit);
575 }
576
577
578 /*
579  * lcp_cilen - Return length of our CI.
580  */
581 static int
582 lcp_cilen(f)
583     fsm *f;
584 {
585     lcp_options *go = &lcp_gotoptions[f->unit];
586
587 #define LENCIVOID(neg)  ((neg) ? CILEN_VOID : 0)
588 #define LENCICHAP(neg)  ((neg) ? CILEN_CHAP : 0)
589 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
590 #define LENCILONG(neg)  ((neg) ? CILEN_LONG : 0)
591 #define LENCILQR(neg)   ((neg) ? CILEN_LQR: 0)
592 #define LENCICBCP(neg)  ((neg) ? CILEN_CBCP: 0)
593     /*
594      * NB: we only ask for one of CHAP and UPAP, even if we will
595      * accept either.
596      */
597     return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
598             LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
599             LENCICHAP(go->neg_chap) +
600             LENCISHORT(!go->neg_chap && go->neg_upap) +
601             LENCILQR(go->neg_lqr) +
602             LENCICBCP(go->neg_cbcp) +
603             LENCILONG(go->neg_magicnumber) +
604             LENCIVOID(go->neg_pcompression) +
605             LENCIVOID(go->neg_accompression) +
606             LENCISHORT(go->neg_mrru) +
607             LENCIVOID(go->neg_ssnhf) +
608             (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
609 }
610
611
612 /*
613  * lcp_addci - Add our desired CIs to a packet.
614  */
615 static void
616 lcp_addci(f, ucp, lenp)
617     fsm *f;
618     u_char *ucp;
619     int *lenp;
620 {
621     lcp_options *go = &lcp_gotoptions[f->unit];
622     u_char *start_ucp = ucp;
623
624 #define ADDCIVOID(opt, neg) \
625     if (neg) { \
626         PUTCHAR(opt, ucp); \
627         PUTCHAR(CILEN_VOID, ucp); \
628     }
629 #define ADDCISHORT(opt, neg, val) \
630     if (neg) { \
631         PUTCHAR(opt, ucp); \
632         PUTCHAR(CILEN_SHORT, ucp); \
633         PUTSHORT(val, ucp); \
634     }
635 #define ADDCICHAP(opt, neg, val, digest) \
636     if (neg) { \
637         PUTCHAR(opt, ucp); \
638         PUTCHAR(CILEN_CHAP, ucp); \
639         PUTSHORT(val, ucp); \
640         PUTCHAR(digest, ucp); \
641     }
642 #define ADDCILONG(opt, neg, val) \
643     if (neg) { \
644         PUTCHAR(opt, ucp); \
645         PUTCHAR(CILEN_LONG, ucp); \
646         PUTLONG(val, ucp); \
647     }
648 #define ADDCILQR(opt, neg, val) \
649     if (neg) { \
650         PUTCHAR(opt, ucp); \
651         PUTCHAR(CILEN_LQR, ucp); \
652         PUTSHORT(PPP_LQR, ucp); \
653         PUTLONG(val, ucp); \
654     }
655 #define ADDCICHAR(opt, neg, val) \
656     if (neg) { \
657         PUTCHAR(opt, ucp); \
658         PUTCHAR(CILEN_CHAR, ucp); \
659         PUTCHAR(val, ucp); \
660     }
661 #define ADDCIENDP(opt, neg, class, val, len) \
662     if (neg) { \
663         int i; \
664         PUTCHAR(opt, ucp); \
665         PUTCHAR(CILEN_CHAR + len, ucp); \
666         PUTCHAR(class, ucp); \
667         for (i = 0; i < len; ++i) \
668             PUTCHAR(val[i], ucp); \
669     }
670
671     ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
672     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
673               go->asyncmap);
674     ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
675     ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
676     ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
677     ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
678     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
679     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
680     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
681     ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
682     ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
683     ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
684               go->endpoint.value, go->endpoint.length);
685
686     if (ucp - start_ucp != *lenp) {
687         /* this should never happen, because peer_mtu should be 1500 */
688         error("Bug in lcp_addci: wrong length");
689     }
690 }
691
692
693 /*
694  * lcp_ackci - Ack our CIs.
695  * This should not modify any state if the Ack is bad.
696  *
697  * Returns:
698  *      0 - Ack was bad.
699  *      1 - Ack was good.
700  */
701 static int
702 lcp_ackci(f, p, len)
703     fsm *f;
704     u_char *p;
705     int len;
706 {
707     lcp_options *go = &lcp_gotoptions[f->unit];
708     u_char cilen, citype, cichar;
709     u_short cishort;
710     u_int32_t cilong;
711
712     /*
713      * CIs must be in exactly the same order that we sent.
714      * Check packet length and CI length at each step.
715      * If we find any deviations, then this packet is bad.
716      */
717 #define ACKCIVOID(opt, neg) \
718     if (neg) { \
719         if ((len -= CILEN_VOID) < 0) \
720             goto bad; \
721         GETCHAR(citype, p); \
722         GETCHAR(cilen, p); \
723         if (cilen != CILEN_VOID || \
724             citype != opt) \
725             goto bad; \
726     }
727 #define ACKCISHORT(opt, neg, val) \
728     if (neg) { \
729         if ((len -= CILEN_SHORT) < 0) \
730             goto bad; \
731         GETCHAR(citype, p); \
732         GETCHAR(cilen, p); \
733         if (cilen != CILEN_SHORT || \
734             citype != opt) \
735             goto bad; \
736         GETSHORT(cishort, p); \
737         if (cishort != val) \
738             goto bad; \
739     }
740 #define ACKCICHAR(opt, neg, val) \
741     if (neg) { \
742         if ((len -= CILEN_CHAR) < 0) \
743             goto bad; \
744         GETCHAR(citype, p); \
745         GETCHAR(cilen, p); \
746         if (cilen != CILEN_CHAR || \
747             citype != opt) \
748             goto bad; \
749         GETCHAR(cichar, p); \
750         if (cichar != val) \
751             goto bad; \
752     }
753 #define ACKCICHAP(opt, neg, val, digest) \
754     if (neg) { \
755         if ((len -= CILEN_CHAP) < 0) \
756             goto bad; \
757         GETCHAR(citype, p); \
758         GETCHAR(cilen, p); \
759         if (cilen != CILEN_CHAP || \
760             citype != opt) \
761             goto bad; \
762         GETSHORT(cishort, p); \
763         if (cishort != val) \
764             goto bad; \
765         GETCHAR(cichar, p); \
766         if (cichar != digest) \
767           goto bad; \
768     }
769 #define ACKCILONG(opt, neg, val) \
770     if (neg) { \
771         if ((len -= CILEN_LONG) < 0) \
772             goto bad; \
773         GETCHAR(citype, p); \
774         GETCHAR(cilen, p); \
775         if (cilen != CILEN_LONG || \
776             citype != opt) \
777             goto bad; \
778         GETLONG(cilong, p); \
779         if (cilong != val) \
780             goto bad; \
781     }
782 #define ACKCILQR(opt, neg, val) \
783     if (neg) { \
784         if ((len -= CILEN_LQR) < 0) \
785             goto bad; \
786         GETCHAR(citype, p); \
787         GETCHAR(cilen, p); \
788         if (cilen != CILEN_LQR || \
789             citype != opt) \
790             goto bad; \
791         GETSHORT(cishort, p); \
792         if (cishort != PPP_LQR) \
793             goto bad; \
794         GETLONG(cilong, p); \
795         if (cilong != val) \
796           goto bad; \
797     }
798 #define ACKCIENDP(opt, neg, class, val, vlen) \
799     if (neg) { \
800         int i; \
801         if ((len -= CILEN_CHAR + vlen) < 0) \
802             goto bad; \
803         GETCHAR(citype, p); \
804         GETCHAR(cilen, p); \
805         if (cilen != CILEN_CHAR + vlen || \
806             citype != opt) \
807             goto bad; \
808         GETCHAR(cichar, p); \
809         if (cichar != class) \
810             goto bad; \
811         for (i = 0; i < vlen; ++i) { \
812             GETCHAR(cichar, p); \
813             if (cichar != val[i]) \
814                 goto bad; \
815         } \
816     }
817
818     ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
819     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
820               go->asyncmap);
821     ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
822     ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
823     ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
824     ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
825     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
826     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
827     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
828     ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
829     ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
830     ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
831               go->endpoint.value, go->endpoint.length);
832
833     /*
834      * If there are any remaining CIs, then this packet is bad.
835      */
836     if (len != 0)
837         goto bad;
838     return (1);
839 bad:
840     LCPDEBUG(("lcp_acki: received bad Ack!"));
841     return (0);
842 }
843
844
845 /*
846  * lcp_nakci - Peer has sent a NAK for some of our CIs.
847  * This should not modify any state if the Nak is bad
848  * or if LCP is in the OPENED state.
849  *
850  * Returns:
851  *      0 - Nak was bad.
852  *      1 - Nak was good.
853  */
854 static int
855 lcp_nakci(f, p, len)
856     fsm *f;
857     u_char *p;
858     int len;
859 {
860     lcp_options *go = &lcp_gotoptions[f->unit];
861     lcp_options *wo = &lcp_wantoptions[f->unit];
862     u_char citype, cichar, *next;
863     u_short cishort;
864     u_int32_t cilong;
865     lcp_options no;             /* options we've seen Naks for */
866     lcp_options try;            /* options to request next time */
867     int looped_back = 0;
868     int cilen;
869
870     BZERO(&no, sizeof(no));
871     try = *go;
872
873     /*
874      * Any Nak'd CIs must be in exactly the same order that we sent.
875      * Check packet length and CI length at each step.
876      * If we find any deviations, then this packet is bad.
877      */
878 #define NAKCIVOID(opt, neg) \
879     if (go->neg && \
880         len >= CILEN_VOID && \
881         p[1] == CILEN_VOID && \
882         p[0] == opt) { \
883         len -= CILEN_VOID; \
884         INCPTR(CILEN_VOID, p); \
885         no.neg = 1; \
886         try.neg = 0; \
887     }
888 #define NAKCICHAP(opt, neg, code) \
889     if (go->neg && \
890         len >= CILEN_CHAP && \
891         p[1] == CILEN_CHAP && \
892         p[0] == opt) { \
893         len -= CILEN_CHAP; \
894         INCPTR(2, p); \
895         GETSHORT(cishort, p); \
896         GETCHAR(cichar, p); \
897         no.neg = 1; \
898         code \
899     }
900 #define NAKCICHAR(opt, neg, code) \
901     if (go->neg && \
902         len >= CILEN_CHAR && \
903         p[1] == CILEN_CHAR && \
904         p[0] == opt) { \
905         len -= CILEN_CHAR; \
906         INCPTR(2, p); \
907         GETCHAR(cichar, p); \
908         no.neg = 1; \
909         code \
910     }
911 #define NAKCISHORT(opt, neg, code) \
912     if (go->neg && \
913         len >= CILEN_SHORT && \
914         p[1] == CILEN_SHORT && \
915         p[0] == opt) { \
916         len -= CILEN_SHORT; \
917         INCPTR(2, p); \
918         GETSHORT(cishort, p); \
919         no.neg = 1; \
920         code \
921     }
922 #define NAKCILONG(opt, neg, code) \
923     if (go->neg && \
924         len >= CILEN_LONG && \
925         p[1] == CILEN_LONG && \
926         p[0] == opt) { \
927         len -= CILEN_LONG; \
928         INCPTR(2, p); \
929         GETLONG(cilong, p); \
930         no.neg = 1; \
931         code \
932     }
933 #define NAKCILQR(opt, neg, code) \
934     if (go->neg && \
935         len >= CILEN_LQR && \
936         p[1] == CILEN_LQR && \
937         p[0] == opt) { \
938         len -= CILEN_LQR; \
939         INCPTR(2, p); \
940         GETSHORT(cishort, p); \
941         GETLONG(cilong, p); \
942         no.neg = 1; \
943         code \
944     }
945 #define NAKCIENDP(opt, neg) \
946     if (go->neg && \
947         len >= CILEN_CHAR && \
948         p[0] == opt && \
949         p[1] >= CILEN_CHAR && \
950         p[1] <= len) { \
951         len -= p[1]; \
952         INCPTR(p[1], p); \
953         no.neg = 1; \
954         try.neg = 0; \
955     }
956
957     /*
958      * We don't care if they want to send us smaller packets than
959      * we want.  Therefore, accept any MRU less than what we asked for,
960      * but then ignore the new value when setting the MRU in the kernel.
961      * If they send us a bigger MRU than what we asked, accept it, up to
962      * the limit of the default MRU we'd get if we didn't negotiate.
963      */
964     if (go->neg_mru && go->mru != DEFMRU) {
965         NAKCISHORT(CI_MRU, neg_mru,
966                    if (cishort <= wo->mru || cishort <= DEFMRU)
967                        try.mru = cishort;
968                    );
969     }
970
971     /*
972      * Add any characters they want to our (receive-side) asyncmap.
973      */
974     if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
975         NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
976                   try.asyncmap = go->asyncmap | cilong;
977                   );
978     }
979
980     /*
981      * If they've nak'd our authentication-protocol, check whether
982      * they are proposing a different protocol, or a different
983      * hash algorithm for CHAP.
984      */
985     if ((go->neg_chap || go->neg_upap)
986         && len >= CILEN_SHORT
987         && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
988         cilen = p[1];
989         len -= cilen;
990         no.neg_chap = go->neg_chap;
991         no.neg_upap = go->neg_upap;
992         INCPTR(2, p);
993         GETSHORT(cishort, p);
994         if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
995             /*
996              * If we were asking for CHAP, they obviously don't want to do it.
997              * If we weren't asking for CHAP, then we were asking for PAP,
998              * in which case this Nak is bad.
999              */
1000             if (!go->neg_chap)
1001                 goto bad;
1002             try.neg_chap = 0;
1003
1004         } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
1005             GETCHAR(cichar, p);
1006             if (go->neg_chap) {
1007                 /*
1008                  * We were asking for CHAP/MD5; they must want a different
1009                  * algorithm.  If they can't do MD5, we can ask for M$-CHAP
1010                  * if we support it, otherwise we'll have to stop
1011                  * asking for CHAP.
1012                  */
1013                 if (cichar != go->chap_mdtype) {
1014 #ifdef CHAPMS
1015                     if (cichar == CHAP_MICROSOFT)
1016                         go->chap_mdtype = CHAP_MICROSOFT;
1017                     else
1018 #endif /* CHAPMS */
1019                         try.neg_chap = 0;
1020                 }
1021             } else {
1022                 /*
1023                  * Stop asking for PAP if we were asking for it.
1024                  */
1025                 try.neg_upap = 0;
1026             }
1027
1028         } else {
1029             /*
1030              * We don't recognize what they're suggesting.
1031              * Stop asking for what we were asking for.
1032              */
1033             if (go->neg_chap)
1034                 try.neg_chap = 0;
1035             else
1036                 try.neg_upap = 0;
1037             p += cilen - CILEN_SHORT;
1038         }
1039     }
1040
1041     /*
1042      * If they can't cope with our link quality protocol, we'll have
1043      * to stop asking for LQR.  We haven't got any other protocol.
1044      * If they Nak the reporting period, take their value XXX ?
1045      */
1046     NAKCILQR(CI_QUALITY, neg_lqr,
1047              if (cishort != PPP_LQR)
1048                  try.neg_lqr = 0;
1049              else
1050                  try.lqr_period = cilong;
1051              );
1052
1053     /*
1054      * Only implementing CBCP...not the rest of the callback options
1055      */
1056     NAKCICHAR(CI_CALLBACK, neg_cbcp,
1057               try.neg_cbcp = 0;
1058               );
1059
1060     /*
1061      * Check for a looped-back line.
1062      */
1063     NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1064               try.magicnumber = magic();
1065               looped_back = 1;
1066               );
1067
1068     /*
1069      * Peer shouldn't send Nak for protocol compression or
1070      * address/control compression requests; they should send
1071      * a Reject instead.  If they send a Nak, treat it as a Reject.
1072      */
1073     NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1074     NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1075
1076     /*
1077      * Nak for MRRU option - accept their value if it is smaller
1078      * than the one we want.
1079      */
1080     if (go->neg_mrru) {
1081         NAKCISHORT(CI_MRRU, neg_mrru,
1082                    if (cishort <= wo->mrru)
1083                        try.mrru = cishort;
1084                    );
1085     }
1086
1087     /*
1088      * Nak for short sequence numbers shouldn't be sent, treat it
1089      * like a reject.
1090      */
1091     NAKCIVOID(CI_SSNHF, neg_ssnhf);
1092
1093     /*
1094      * Nak of the endpoint discriminator option is not permitted,
1095      * treat it like a reject.
1096      */
1097     NAKCIENDP(CI_EPDISC, neg_endpoint);
1098
1099     /*
1100      * There may be remaining CIs, if the peer is requesting negotiation
1101      * on an option that we didn't include in our request packet.
1102      * If we see an option that we requested, or one we've already seen
1103      * in this packet, then this packet is bad.
1104      * If we wanted to respond by starting to negotiate on the requested
1105      * option(s), we could, but we don't, because except for the
1106      * authentication type and quality protocol, if we are not negotiating
1107      * an option, it is because we were told not to.
1108      * For the authentication type, the Nak from the peer means
1109      * `let me authenticate myself with you' which is a bit pointless.
1110      * For the quality protocol, the Nak means `ask me to send you quality
1111      * reports', but if we didn't ask for them, we don't want them.
1112      * An option we don't recognize represents the peer asking to
1113      * negotiate some option we don't support, so ignore it.
1114      */
1115     while (len > CILEN_VOID) {
1116         GETCHAR(citype, p);
1117         GETCHAR(cilen, p);
1118         if (cilen < CILEN_VOID || (len -= cilen) < 0)
1119             goto bad;
1120         next = p + cilen - 2;
1121
1122         switch (citype) {
1123         case CI_MRU:
1124             if ((go->neg_mru && go->mru != DEFMRU)
1125                 || no.neg_mru || cilen != CILEN_SHORT)
1126                 goto bad;
1127             GETSHORT(cishort, p);
1128             if (cishort < DEFMRU) {
1129                 try.neg_mru = 1;
1130                 try.mru = cishort;
1131             }
1132             break;
1133         case CI_ASYNCMAP:
1134             if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1135                 || no.neg_asyncmap || cilen != CILEN_LONG)
1136                 goto bad;
1137             break;
1138         case CI_AUTHTYPE:
1139             if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
1140                 goto bad;
1141             break;
1142         case CI_MAGICNUMBER:
1143             if (go->neg_magicnumber || no.neg_magicnumber ||
1144                 cilen != CILEN_LONG)
1145                 goto bad;
1146             break;
1147         case CI_PCOMPRESSION:
1148             if (go->neg_pcompression || no.neg_pcompression
1149                 || cilen != CILEN_VOID)
1150                 goto bad;
1151             break;
1152         case CI_ACCOMPRESSION:
1153             if (go->neg_accompression || no.neg_accompression
1154                 || cilen != CILEN_VOID)
1155                 goto bad;
1156             break;
1157         case CI_QUALITY:
1158             if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1159                 goto bad;
1160             break;
1161         case CI_MRRU:
1162             if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1163                 goto bad;
1164             break;
1165         case CI_SSNHF:
1166             if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1167                 goto bad;
1168             try.neg_ssnhf = 1;
1169             break;
1170         case CI_EPDISC:
1171             if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1172                 goto bad;
1173             break;
1174         }
1175         p = next;
1176     }
1177
1178     /*
1179      * OK, the Nak is good.  Now we can update state.
1180      * If there are any options left we ignore them.
1181      */
1182     if (f->state != OPENED) {
1183         if (looped_back) {
1184             if (++try.numloops >= lcp_loopbackfail) {
1185                 notice("Serial line is looped back.");
1186                 lcp_close(f->unit, "Loopback detected");
1187                 status = EXIT_LOOPBACK;
1188             }
1189         } else
1190             try.numloops = 0;
1191         *go = try;
1192     }
1193
1194     return 1;
1195
1196 bad:
1197     LCPDEBUG(("lcp_nakci: received bad Nak!"));
1198     return 0;
1199 }
1200
1201
1202 /*
1203  * lcp_rejci - Peer has Rejected some of our CIs.
1204  * This should not modify any state if the Reject is bad
1205  * or if LCP is in the OPENED state.
1206  *
1207  * Returns:
1208  *      0 - Reject was bad.
1209  *      1 - Reject was good.
1210  */
1211 static int
1212 lcp_rejci(f, p, len)
1213     fsm *f;
1214     u_char *p;
1215     int len;
1216 {
1217     lcp_options *go = &lcp_gotoptions[f->unit];
1218     u_char cichar;
1219     u_short cishort;
1220     u_int32_t cilong;
1221     lcp_options try;            /* options to request next time */
1222
1223     try = *go;
1224
1225     /*
1226      * Any Rejected CIs must be in exactly the same order that we sent.
1227      * Check packet length and CI length at each step.
1228      * If we find any deviations, then this packet is bad.
1229      */
1230 #define REJCIVOID(opt, neg) \
1231     if (go->neg && \
1232         len >= CILEN_VOID && \
1233         p[1] == CILEN_VOID && \
1234         p[0] == opt) { \
1235         len -= CILEN_VOID; \
1236         INCPTR(CILEN_VOID, p); \
1237         try.neg = 0; \
1238     }
1239 #define REJCISHORT(opt, neg, val) \
1240     if (go->neg && \
1241         len >= CILEN_SHORT && \
1242         p[1] == CILEN_SHORT && \
1243         p[0] == opt) { \
1244         len -= CILEN_SHORT; \
1245         INCPTR(2, p); \
1246         GETSHORT(cishort, p); \
1247         /* Check rejected value. */ \
1248         if (cishort != val) \
1249             goto bad; \
1250         try.neg = 0; \
1251     }
1252 #define REJCICHAP(opt, neg, val, digest) \
1253     if (go->neg && \
1254         len >= CILEN_CHAP && \
1255         p[1] == CILEN_CHAP && \
1256         p[0] == opt) { \
1257         len -= CILEN_CHAP; \
1258         INCPTR(2, p); \
1259         GETSHORT(cishort, p); \
1260         GETCHAR(cichar, p); \
1261         /* Check rejected value. */ \
1262         if (cishort != val || cichar != digest) \
1263             goto bad; \
1264         try.neg = 0; \
1265         try.neg_upap = 0; \
1266     }
1267 #define REJCILONG(opt, neg, val) \
1268     if (go->neg && \
1269         len >= CILEN_LONG && \
1270         p[1] == CILEN_LONG && \
1271         p[0] == opt) { \
1272         len -= CILEN_LONG; \
1273         INCPTR(2, p); \
1274         GETLONG(cilong, p); \
1275         /* Check rejected value. */ \
1276         if (cilong != val) \
1277             goto bad; \
1278         try.neg = 0; \
1279     }
1280 #define REJCILQR(opt, neg, val) \
1281     if (go->neg && \
1282         len >= CILEN_LQR && \
1283         p[1] == CILEN_LQR && \
1284         p[0] == opt) { \
1285         len -= CILEN_LQR; \
1286         INCPTR(2, p); \
1287         GETSHORT(cishort, p); \
1288         GETLONG(cilong, p); \
1289         /* Check rejected value. */ \
1290         if (cishort != PPP_LQR || cilong != val) \
1291             goto bad; \
1292         try.neg = 0; \
1293     }
1294 #define REJCICBCP(opt, neg, val) \
1295     if (go->neg && \
1296         len >= CILEN_CBCP && \
1297         p[1] == CILEN_CBCP && \
1298         p[0] == opt) { \
1299         len -= CILEN_CBCP; \
1300         INCPTR(2, p); \
1301         GETCHAR(cichar, p); \
1302         /* Check rejected value. */ \
1303         if (cichar != val) \
1304             goto bad; \
1305         try.neg = 0; \
1306     }
1307 #define REJCIENDP(opt, neg, class, val, vlen) \
1308     if (go->neg && \
1309         len >= CILEN_CHAR + vlen && \
1310         p[0] == opt && \
1311         p[1] == CILEN_CHAR + vlen) { \
1312         int i; \
1313         len -= CILEN_CHAR + vlen; \
1314         INCPTR(2, p); \
1315         GETCHAR(cichar, p); \
1316         if (cichar != class) \
1317             goto bad; \
1318         for (i = 0; i < vlen; ++i) { \
1319             GETCHAR(cichar, p); \
1320             if (cichar != val[i]) \
1321                 goto bad; \
1322         } \
1323         try.neg = 0; \
1324     }
1325
1326     REJCISHORT(CI_MRU, neg_mru, go->mru);
1327     REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1328     REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
1329     if (!go->neg_chap) {
1330         REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1331     }
1332     REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1333     REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1334     REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1335     REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1336     REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1337     REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1338     REJCIVOID(CI_SSNHF, neg_ssnhf);
1339     REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class,
1340               go->endpoint.value, go->endpoint.length);
1341
1342     /*
1343      * If there are any remaining CIs, then this packet is bad.
1344      */
1345     if (len != 0)
1346         goto bad;
1347     /*
1348      * Now we can update state.
1349      */
1350     if (f->state != OPENED)
1351         *go = try;
1352     return 1;
1353
1354 bad:
1355     LCPDEBUG(("lcp_rejci: received bad Reject!"));
1356     return 0;
1357 }
1358
1359
1360 /*
1361  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1362  *
1363  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1364  * appropriately.  If reject_if_disagree is non-zero, doesn't return
1365  * CONFNAK; returns CONFREJ if it can't return CONFACK.
1366  */
1367 static int
1368 lcp_reqci(f, inp, lenp, reject_if_disagree)
1369     fsm *f;
1370     u_char *inp;                /* Requested CIs */
1371     int *lenp;                  /* Length of requested CIs */
1372     int reject_if_disagree;
1373 {
1374     lcp_options *go = &lcp_gotoptions[f->unit];
1375     lcp_options *ho = &lcp_hisoptions[f->unit];
1376     lcp_options *ao = &lcp_allowoptions[f->unit];
1377     u_char *cip, *next;         /* Pointer to current and next CIs */
1378     int cilen, citype, cichar;  /* Parsed len, type, char value */
1379     u_short cishort;            /* Parsed short value */
1380     u_int32_t cilong;           /* Parse long value */
1381     int rc = CONFACK;           /* Final packet return code */
1382     int orc;                    /* Individual option return code */
1383     u_char *p;                  /* Pointer to next char to parse */
1384     u_char *rejp;               /* Pointer to next char in reject frame */
1385     u_char *nakp;               /* Pointer to next char in Nak frame */
1386     int l = *lenp;              /* Length left */
1387
1388     /*
1389      * Reset all his options.
1390      */
1391     BZERO(ho, sizeof(*ho));
1392
1393     /*
1394      * Process all his options.
1395      */
1396     next = inp;
1397     nakp = nak_buffer;
1398     rejp = inp;
1399     while (l) {
1400         orc = CONFACK;                  /* Assume success */
1401         cip = p = next;                 /* Remember begining of CI */
1402         if (l < 2 ||                    /* Not enough data for CI header or */
1403             p[1] < 2 ||                 /*  CI length too small or */
1404             p[1] > l) {                 /*  CI length too big? */
1405             LCPDEBUG(("lcp_reqci: bad CI length!"));
1406             orc = CONFREJ;              /* Reject bad CI */
1407             cilen = l;                  /* Reject till end of packet */
1408             l = 0;                      /* Don't loop again */
1409             citype = 0;
1410             goto endswitch;
1411         }
1412         GETCHAR(citype, p);             /* Parse CI type */
1413         GETCHAR(cilen, p);              /* Parse CI length */
1414         l -= cilen;                     /* Adjust remaining length */
1415         next += cilen;                  /* Step to next CI */
1416
1417         switch (citype) {               /* Check CI type */
1418         case CI_MRU:
1419             if (!ao->neg_mru ||         /* Allow option? */
1420                 cilen != CILEN_SHORT) { /* Check CI length */
1421                 orc = CONFREJ;          /* Reject CI */
1422                 break;
1423             }
1424             GETSHORT(cishort, p);       /* Parse MRU */
1425
1426             /*
1427              * He must be able to receive at least our minimum.
1428              * No need to check a maximum.  If he sends a large number,
1429              * we'll just ignore it.
1430              */
1431             if (cishort < MINMRU) {
1432                 orc = CONFNAK;          /* Nak CI */
1433                 PUTCHAR(CI_MRU, nakp);
1434                 PUTCHAR(CILEN_SHORT, nakp);
1435                 PUTSHORT(MINMRU, nakp); /* Give him a hint */
1436                 break;
1437             }
1438             ho->neg_mru = 1;            /* Remember he sent MRU */
1439             ho->mru = cishort;          /* And remember value */
1440             break;
1441
1442         case CI_ASYNCMAP:
1443             if (!ao->neg_asyncmap ||
1444                 cilen != CILEN_LONG) {
1445                 orc = CONFREJ;
1446                 break;
1447             }
1448             GETLONG(cilong, p);
1449
1450             /*
1451              * Asyncmap must have set at least the bits
1452              * which are set in lcp_allowoptions[unit].asyncmap.
1453              */
1454             if ((ao->asyncmap & ~cilong) != 0) {
1455                 orc = CONFNAK;
1456                 PUTCHAR(CI_ASYNCMAP, nakp);
1457                 PUTCHAR(CILEN_LONG, nakp);
1458                 PUTLONG(ao->asyncmap | cilong, nakp);
1459                 break;
1460             }
1461             ho->neg_asyncmap = 1;
1462             ho->asyncmap = cilong;
1463             break;
1464
1465         case CI_AUTHTYPE:
1466             if (cilen < CILEN_SHORT ||
1467                 !(ao->neg_upap || ao->neg_chap)) {
1468                 /*
1469                  * Reject the option if we're not willing to authenticate.
1470                  */
1471                 orc = CONFREJ;
1472                 break;
1473             }
1474             GETSHORT(cishort, p);
1475
1476             /*
1477              * Authtype must be PAP or CHAP.
1478              *
1479              * Note: if both ao->neg_upap and ao->neg_chap are set,
1480              * and the peer sends a Configure-Request with two
1481              * authenticate-protocol requests, one for CHAP and one
1482              * for UPAP, then we will reject the second request.
1483              * Whether we end up doing CHAP or UPAP depends then on
1484              * the ordering of the CIs in the peer's Configure-Request.
1485              */
1486
1487             if (cishort == PPP_PAP) {
1488                 if (ho->neg_chap ||     /* we've already accepted CHAP */
1489                     cilen != CILEN_SHORT) {
1490                     LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1491                     orc = CONFREJ;
1492                     break;
1493                 }
1494                 if (!ao->neg_upap) {    /* we don't want to do PAP */
1495                     orc = CONFNAK;      /* NAK it and suggest CHAP */
1496                     PUTCHAR(CI_AUTHTYPE, nakp);
1497                     PUTCHAR(CILEN_CHAP, nakp);
1498                     PUTSHORT(PPP_CHAP, nakp);
1499                     PUTCHAR(ao->chap_mdtype, nakp);
1500                     /* XXX if we can do CHAP_MICROSOFT as well, we should
1501                        probably put in another option saying so */
1502                     break;
1503                 }
1504                 ho->neg_upap = 1;
1505                 break;
1506             }
1507             if (cishort == PPP_CHAP) {
1508                 if (ho->neg_upap ||     /* we've already accepted PAP */
1509                     cilen != CILEN_CHAP) {
1510                     LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
1511                     orc = CONFREJ;
1512                     break;
1513                 }
1514                 if (!ao->neg_chap) {    /* we don't want to do CHAP */
1515                     orc = CONFNAK;      /* NAK it and suggest PAP */
1516                     PUTCHAR(CI_AUTHTYPE, nakp);
1517                     PUTCHAR(CILEN_SHORT, nakp);
1518                     PUTSHORT(PPP_PAP, nakp);
1519                     break;
1520                 }
1521                 GETCHAR(cichar, p);     /* get digest type*/
1522                 if (cichar != CHAP_DIGEST_MD5
1523 #ifdef CHAPMS
1524                     && cichar != CHAP_MICROSOFT
1525 #endif
1526                     ) {
1527                     orc = CONFNAK;
1528                     PUTCHAR(CI_AUTHTYPE, nakp);
1529                     PUTCHAR(CILEN_CHAP, nakp);
1530                     PUTSHORT(PPP_CHAP, nakp);
1531                     PUTCHAR(ao->chap_mdtype, nakp);
1532                     break;
1533                 }
1534                 ho->chap_mdtype = cichar; /* save md type */
1535                 ho->neg_chap = 1;
1536                 break;
1537             }
1538
1539             /*
1540              * We don't recognize the protocol they're asking for.
1541              * Nak it with something we're willing to do.
1542              * (At this point we know ao->neg_upap || ao->neg_chap.)
1543              */
1544             orc = CONFNAK;
1545             PUTCHAR(CI_AUTHTYPE, nakp);
1546             if (ao->neg_chap) {
1547                 PUTCHAR(CILEN_CHAP, nakp);
1548                 PUTSHORT(PPP_CHAP, nakp);
1549                 PUTCHAR(ao->chap_mdtype, nakp);
1550             } else {
1551                 PUTCHAR(CILEN_SHORT, nakp);
1552                 PUTSHORT(PPP_PAP, nakp);
1553             }
1554             break;
1555
1556         case CI_QUALITY:
1557             if (!ao->neg_lqr ||
1558                 cilen != CILEN_LQR) {
1559                 orc = CONFREJ;
1560                 break;
1561             }
1562
1563             GETSHORT(cishort, p);
1564             GETLONG(cilong, p);
1565
1566             /*
1567              * Check the protocol and the reporting period.
1568              * XXX When should we Nak this, and what with?
1569              */
1570             if (cishort != PPP_LQR) {
1571                 orc = CONFNAK;
1572                 PUTCHAR(CI_QUALITY, nakp);
1573                 PUTCHAR(CILEN_LQR, nakp);
1574                 PUTSHORT(PPP_LQR, nakp);
1575                 PUTLONG(ao->lqr_period, nakp);
1576                 break;
1577             }
1578             break;
1579
1580         case CI_MAGICNUMBER:
1581             if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
1582                 cilen != CILEN_LONG) {
1583                 orc = CONFREJ;
1584                 break;
1585             }
1586             GETLONG(cilong, p);
1587
1588             /*
1589              * He must have a different magic number.
1590              */
1591             if (go->neg_magicnumber &&
1592                 cilong == go->magicnumber) {
1593                 cilong = magic();       /* Don't put magic() inside macro! */
1594                 orc = CONFNAK;
1595                 PUTCHAR(CI_MAGICNUMBER, nakp);
1596                 PUTCHAR(CILEN_LONG, nakp);
1597                 PUTLONG(cilong, nakp);
1598                 break;
1599             }
1600             ho->neg_magicnumber = 1;
1601             ho->magicnumber = cilong;
1602             break;
1603
1604
1605         case CI_PCOMPRESSION:
1606             if (!ao->neg_pcompression ||
1607                 cilen != CILEN_VOID) {
1608                 orc = CONFREJ;
1609                 break;
1610             }
1611             ho->neg_pcompression = 1;
1612             break;
1613
1614         case CI_ACCOMPRESSION:
1615             if (!ao->neg_accompression ||
1616                 cilen != CILEN_VOID) {
1617                 orc = CONFREJ;
1618                 break;
1619             }
1620             ho->neg_accompression = 1;
1621             break;
1622
1623         case CI_MRRU:
1624             if (!ao->neg_mrru || !multilink ||
1625                 cilen != CILEN_SHORT) {
1626                 orc = CONFREJ;
1627                 break;
1628             }
1629
1630             GETSHORT(cishort, p);
1631             /* possibly should insist on a minimum/maximum MRRU here */
1632             ho->neg_mrru = 1;
1633             ho->mrru = cishort;
1634             break;
1635
1636         case CI_SSNHF:
1637             if (!ao->neg_ssnhf || !multilink ||
1638                 cilen != CILEN_VOID) {
1639                 orc = CONFREJ;
1640                 break;
1641             }
1642             ho->neg_ssnhf = 1;
1643             break;
1644
1645         case CI_EPDISC:
1646             if (!ao->neg_endpoint ||
1647                 cilen < CILEN_CHAR ||
1648                 cilen > CILEN_CHAR + MAX_ENDP_LEN) {
1649                 orc = CONFREJ;
1650                 break;
1651             }
1652             GETCHAR(cichar, p);
1653             cilen -= CILEN_CHAR;
1654             ho->neg_endpoint = 1;
1655             ho->endpoint.class = cichar;
1656             ho->endpoint.length = cilen;
1657             BCOPY(p, ho->endpoint.value, cilen);
1658             INCPTR(cilen, p);
1659             break;
1660
1661         default:
1662             LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
1663             orc = CONFREJ;
1664             break;
1665         }
1666
1667 endswitch:
1668         if (orc == CONFACK &&           /* Good CI */
1669             rc != CONFACK)              /*  but prior CI wasnt? */
1670             continue;                   /* Don't send this one */
1671
1672         if (orc == CONFNAK) {           /* Nak this CI? */
1673             if (reject_if_disagree      /* Getting fed up with sending NAKs? */
1674                 && citype != CI_MAGICNUMBER) {
1675                 orc = CONFREJ;          /* Get tough if so */
1676             } else {
1677                 if (rc == CONFREJ)      /* Rejecting prior CI? */
1678                     continue;           /* Don't send this one */
1679                 rc = CONFNAK;
1680             }
1681         }
1682         if (orc == CONFREJ) {           /* Reject this CI */
1683             rc = CONFREJ;
1684             if (cip != rejp)            /* Need to move rejected CI? */
1685                 BCOPY(cip, rejp, cilen); /* Move it */
1686             INCPTR(cilen, rejp);        /* Update output pointer */
1687         }
1688     }
1689
1690     /*
1691      * If we wanted to send additional NAKs (for unsent CIs), the
1692      * code would go here.  The extra NAKs would go at *nakp.
1693      * At present there are no cases where we want to ask the
1694      * peer to negotiate an option.
1695      */
1696
1697     switch (rc) {
1698     case CONFACK:
1699         *lenp = next - inp;
1700         break;
1701     case CONFNAK:
1702         /*
1703          * Copy the Nak'd options from the nak_buffer to the caller's buffer.
1704          */
1705         *lenp = nakp - nak_buffer;
1706         BCOPY(nak_buffer, inp, *lenp);
1707         break;
1708     case CONFREJ:
1709         *lenp = rejp - inp;
1710         break;
1711     }
1712
1713     LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
1714     return (rc);                        /* Return final code */
1715 }
1716
1717
1718 /*
1719  * lcp_up - LCP has come UP.
1720  */
1721 static void
1722 lcp_up(f)
1723     fsm *f;
1724 {
1725     lcp_options *wo = &lcp_wantoptions[f->unit];
1726     lcp_options *ho = &lcp_hisoptions[f->unit];
1727     lcp_options *go = &lcp_gotoptions[f->unit];
1728     lcp_options *ao = &lcp_allowoptions[f->unit];
1729
1730     if (!go->neg_magicnumber)
1731         go->magicnumber = 0;
1732     if (!ho->neg_magicnumber)
1733         ho->magicnumber = 0;
1734
1735     /*
1736      * Set our MTU to the smaller of the MTU we wanted and
1737      * the MRU our peer wanted.  If we negotiated an MRU,
1738      * set our MRU to the larger of value we wanted and
1739      * the value we got in the negotiation.
1740      */
1741     ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
1742                     (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
1743                     ho->neg_pcompression, ho->neg_accompression);
1744     ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
1745                     (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
1746                     go->neg_pcompression, go->neg_accompression);
1747
1748     if (ho->neg_mru)
1749         peer_mru[f->unit] = ho->mru;
1750
1751     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
1752
1753     link_established(f->unit);
1754 }
1755
1756
1757 /*
1758  * lcp_down - LCP has gone DOWN.
1759  *
1760  * Alert other protocols.
1761  */
1762 static void
1763 lcp_down(f)
1764     fsm *f;
1765 {
1766     lcp_options *go = &lcp_gotoptions[f->unit];
1767
1768     lcp_echo_lowerdown(f->unit);
1769
1770     link_down(f->unit);
1771
1772     ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
1773     ppp_recv_config(f->unit, PPP_MRU,
1774                     (go->neg_asyncmap? go->asyncmap: 0xffffffff),
1775                     go->neg_pcompression, go->neg_accompression);
1776     peer_mru[f->unit] = PPP_MRU;
1777 }
1778
1779
1780 /*
1781  * lcp_starting - LCP needs the lower layer up.
1782  */
1783 static void
1784 lcp_starting(f)
1785     fsm *f;
1786 {
1787     link_required(f->unit);
1788 }
1789
1790
1791 /*
1792  * lcp_finished - LCP has finished with the lower layer.
1793  */
1794 static void
1795 lcp_finished(f)
1796     fsm *f;
1797 {
1798     link_terminated(f->unit);
1799 }
1800
1801
1802 /*
1803  * lcp_printpkt - print the contents of an LCP packet.
1804  */
1805 static char *lcp_codenames[] = {
1806     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1807     "TermReq", "TermAck", "CodeRej", "ProtRej",
1808     "EchoReq", "EchoRep", "DiscReq"
1809 };
1810
1811 static int
1812 lcp_printpkt(p, plen, printer, arg)
1813     u_char *p;
1814     int plen;
1815     void (*printer) __P((void *, char *, ...));
1816     void *arg;
1817 {
1818     int code, id, len, olen, i;
1819     u_char *pstart, *optend;
1820     u_short cishort;
1821     u_int32_t cilong;
1822
1823     if (plen < HEADERLEN)
1824         return 0;
1825     pstart = p;
1826     GETCHAR(code, p);
1827     GETCHAR(id, p);
1828     GETSHORT(len, p);
1829     if (len < HEADERLEN || len > plen)
1830         return 0;
1831
1832     if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
1833         printer(arg, " %s", lcp_codenames[code-1]);
1834     else
1835         printer(arg, " code=0x%x", code);
1836     printer(arg, " id=0x%x", id);
1837     len -= HEADERLEN;
1838     switch (code) {
1839     case CONFREQ:
1840     case CONFACK:
1841     case CONFNAK:
1842     case CONFREJ:
1843         /* print option list */
1844         while (len >= 2) {
1845             GETCHAR(code, p);
1846             GETCHAR(olen, p);
1847             p -= 2;
1848             if (olen < 2 || olen > len) {
1849                 break;
1850             }
1851             printer(arg, " <");
1852             len -= olen;
1853             optend = p + olen;
1854             switch (code) {
1855             case CI_MRU:
1856                 if (olen == CILEN_SHORT) {
1857                     p += 2;
1858                     GETSHORT(cishort, p);
1859                     printer(arg, "mru %d", cishort);
1860                 }
1861                 break;
1862             case CI_ASYNCMAP:
1863                 if (olen == CILEN_LONG) {
1864                     p += 2;
1865                     GETLONG(cilong, p);
1866                     printer(arg, "asyncmap 0x%x", cilong);
1867                 }
1868                 break;
1869             case CI_AUTHTYPE:
1870                 if (olen >= CILEN_SHORT) {
1871                     p += 2;
1872                     printer(arg, "auth ");
1873                     GETSHORT(cishort, p);
1874                     switch (cishort) {
1875                     case PPP_PAP:
1876                         printer(arg, "pap");
1877                         break;
1878                     case PPP_CHAP:
1879                         printer(arg, "chap");
1880                         if (p < optend) {
1881                             switch (*p) {
1882                             case CHAP_DIGEST_MD5:
1883                                 printer(arg, " MD5");
1884                                 ++p;
1885                                 break;
1886 #ifdef CHAPMS
1887                             case CHAP_MICROSOFT:
1888                                 printer(arg, " m$oft");
1889                                 ++p;
1890                                 break;
1891 #endif
1892                             }
1893                         }
1894                         break;
1895                     default:
1896                         printer(arg, "0x%x", cishort);
1897                     }
1898                 }
1899                 break;
1900             case CI_QUALITY:
1901                 if (olen >= CILEN_SHORT) {
1902                     p += 2;
1903                     printer(arg, "quality ");
1904                     GETSHORT(cishort, p);
1905                     switch (cishort) {
1906                     case PPP_LQR:
1907                         printer(arg, "lqr");
1908                         break;
1909                     default:
1910                         printer(arg, "0x%x", cishort);
1911                     }
1912                 }
1913                 break;
1914             case CI_CALLBACK:
1915                 if (olen >= CILEN_CHAR) {
1916                     p += 2;
1917                     printer(arg, "callback ");
1918                     GETCHAR(cishort, p);
1919                     switch (cishort) {
1920                     case CBCP_OPT:
1921                         printer(arg, "CBCP");
1922                         break;
1923                     default:
1924                         printer(arg, "0x%x", cishort);
1925                     }
1926                 }
1927                 break;
1928             case CI_MAGICNUMBER:
1929                 if (olen == CILEN_LONG) {
1930                     p += 2;
1931                     GETLONG(cilong, p);
1932                     printer(arg, "magic 0x%x", cilong);
1933                 }
1934                 break;
1935             case CI_PCOMPRESSION:
1936                 if (olen == CILEN_VOID) {
1937                     p += 2;
1938                     printer(arg, "pcomp");
1939                 }
1940                 break;
1941             case CI_ACCOMPRESSION:
1942                 if (olen == CILEN_VOID) {
1943                     p += 2;
1944                     printer(arg, "accomp");
1945                 }
1946                 break;
1947             case CI_MRRU:
1948                 if (olen == CILEN_SHORT) {
1949                     p += 2;
1950                     GETSHORT(cishort, p);
1951                     printer(arg, "mrru %d", cishort);
1952                 }
1953                 break;
1954             case CI_SSNHF:
1955                 if (olen == CILEN_VOID) {
1956                     p += 2;
1957                     printer(arg, "ssnhf");
1958                 }
1959                 break;
1960             case CI_EPDISC:
1961 #ifdef HAVE_MULTILINK
1962                 if (olen >= CILEN_CHAR) {
1963                     struct epdisc epd;
1964                     p += 2;
1965                     GETCHAR(epd.class, p);
1966                     epd.length = olen - CILEN_CHAR;
1967                     if (epd.length > MAX_ENDP_LEN)
1968                         epd.length = MAX_ENDP_LEN;
1969                     if (epd.length > 0) {
1970                         BCOPY(p, epd.value, epd.length);
1971                         p += epd.length;
1972                     }
1973                     printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
1974                 }
1975 #else
1976                 printer(arg, "endpoint");
1977 #endif
1978                 break;
1979             }
1980             while (p < optend) {
1981                 GETCHAR(code, p);
1982                 printer(arg, " %.2x", code);
1983             }
1984             printer(arg, ">");
1985         }
1986         break;
1987
1988     case TERMACK:
1989     case TERMREQ:
1990         if (len > 0 && *p >= ' ' && *p < 0x7f) {
1991             printer(arg, " ");
1992             print_string((char *)p, len, printer, arg);
1993             p += len;
1994             len = 0;
1995         }
1996         break;
1997
1998     case ECHOREQ:
1999     case ECHOREP:
2000     case DISCREQ:
2001         if (len >= 4) {
2002             GETLONG(cilong, p);
2003             printer(arg, " magic=0x%x", cilong);
2004             p += 4;
2005             len -= 4;
2006         }
2007         break;
2008     }
2009
2010     /* print the rest of the bytes in the packet */
2011     for (i = 0; i < len && i < 32; ++i) {
2012         GETCHAR(code, p);
2013         printer(arg, " %.2x", code);
2014     }
2015     if (i < len) {
2016         printer(arg, " ...");
2017         p += len - i;
2018     }
2019
2020     return p - pstart;
2021 }
2022
2023 /*
2024  * Time to shut down the link because there is nothing out there.
2025  */
2026
2027 static
2028 void LcpLinkFailure (f)
2029     fsm *f;
2030 {
2031     if (f->state == OPENED) {
2032         info("No response to %d echo-requests", lcp_echos_pending);
2033         notice("Serial link appears to be disconnected.");
2034         lcp_close(f->unit, "Peer not responding");
2035         status = EXIT_PEER_DEAD;
2036     }
2037 }
2038
2039 /*
2040  * Timer expired for the LCP echo requests from this process.
2041  */
2042
2043 static void
2044 LcpEchoCheck (f)
2045     fsm *f;
2046 {
2047     LcpSendEchoRequest (f);
2048     if (f->state != OPENED)
2049         return;
2050
2051     /*
2052      * Start the timer for the next interval.
2053      */
2054     if (lcp_echo_timer_running)
2055         warn("assertion lcp_echo_timer_running==0 failed");
2056     TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
2057     lcp_echo_timer_running = 1;
2058 }
2059
2060 /*
2061  * LcpEchoTimeout - Timer expired on the LCP echo
2062  */
2063
2064 static void
2065 LcpEchoTimeout (arg)
2066     void *arg;
2067 {
2068     if (lcp_echo_timer_running != 0) {
2069         lcp_echo_timer_running = 0;
2070         LcpEchoCheck ((fsm *) arg);
2071     }
2072 }
2073
2074 /*
2075  * LcpEchoReply - LCP has received a reply to the echo
2076  */
2077
2078 static void
2079 lcp_received_echo_reply (f, id, inp, len)
2080     fsm *f;
2081     int id;
2082     u_char *inp;
2083     int len;
2084 {
2085     u_int32_t magic;
2086
2087     /* Check the magic number - don't count replies from ourselves. */
2088     if (len < 4) {
2089         dbglog("lcp: received short Echo-Reply, length %d", len);
2090         return;
2091     }
2092     GETLONG(magic, inp);
2093     if (lcp_gotoptions[f->unit].neg_magicnumber
2094         && magic == lcp_gotoptions[f->unit].magicnumber) {
2095         warn("appear to have received our own echo-reply!");
2096         return;
2097     }
2098
2099     /* Reset the number of outstanding echo frames */
2100     lcp_echos_pending = 0;
2101 }
2102
2103 /*
2104  * LcpSendEchoRequest - Send an echo request frame to the peer
2105  */
2106
2107 static void
2108 LcpSendEchoRequest (f)
2109     fsm *f;
2110 {
2111     u_int32_t lcp_magic;
2112     u_char pkt[4], *pktp;
2113
2114     /*
2115      * Detect the failure of the peer at this point.
2116      */
2117     if (lcp_echo_fails != 0) {
2118         if (lcp_echos_pending >= lcp_echo_fails) {
2119             LcpLinkFailure(f);
2120             lcp_echos_pending = 0;
2121         }
2122     }
2123
2124     /*
2125      * Make and send the echo request frame.
2126      */
2127     if (f->state == OPENED) {
2128         lcp_magic = lcp_gotoptions[f->unit].magicnumber;
2129         pktp = pkt;
2130         PUTLONG(lcp_magic, pktp);
2131         fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
2132         ++lcp_echos_pending;
2133     }
2134 }
2135
2136 /*
2137  * lcp_echo_lowerup - Start the timer for the LCP frame
2138  */
2139
2140 static void
2141 lcp_echo_lowerup (unit)
2142     int unit;
2143 {
2144     fsm *f = &lcp_fsm[unit];
2145
2146     /* Clear the parameters for generating echo frames */
2147     lcp_echos_pending      = 0;
2148     lcp_echo_number        = 0;
2149     lcp_echo_timer_running = 0;
2150   
2151     /* If a timeout interval is specified then start the timer */
2152     if (lcp_echo_interval != 0)
2153         LcpEchoCheck (f);
2154 }
2155
2156 /*
2157  * lcp_echo_lowerdown - Stop the timer for the LCP frame
2158  */
2159
2160 static void
2161 lcp_echo_lowerdown (unit)
2162     int unit;
2163 {
2164     fsm *f = &lcp_fsm[unit];
2165
2166     if (lcp_echo_timer_running != 0) {
2167         UNTIMEOUT (LcpEchoTimeout, f);
2168         lcp_echo_timer_running = 0;
2169     }
2170 }