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