Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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