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