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