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