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