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