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