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