ReactOS 0.4.16-dev-819-g75c0dc0
lcp.c
Go to the documentation of this file.
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
73static void lcp_delayed_up(void *arg);
74
75/*
76 * LCP-related command-line options.
77 */
78#if 0 /* UNUSED */
79int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
80int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
81#endif /* UNUSED */
82
83#if 0 /* UNUSED */
84/* options */
85static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
86static 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
91bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */
92#endif
93bool lax_recv = 0; /* accept control chars in asyncmap */
94bool noendpoint = 0; /* don't send/accept endpoint discriminator */
95#endif /* UNUSED */
96
97#if PPP_OPTIONS
98static int noopt (char **);
99#endif /* PPP_OPTIONS */
100
101#ifdef HAVE_MULTILINK
102static int setendpoint (char **);
103static void printendpoint (option_t *, void (*)(void *, char *, ...),
104 void *);
105#endif /* HAVE_MULTILINK */
106
107#if PPP_OPTIONS
108static 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 */
218static void lcp_resetci(fsm *f); /* Reset our CI */
219static int lcp_cilen(fsm *f); /* Return length of our CI */
220static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */
221static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */
222static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */
223static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */
224static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */
225static void lcp_up(fsm *f); /* We're UP */
226static void lcp_down(fsm *f); /* We're DOWN */
227static void lcp_starting (fsm *); /* We need lower layer up */
228static void lcp_finished (fsm *); /* We need lower layer down */
229static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len);
230static void lcp_rprotrej(fsm *f, u_char *inp, int len);
231
232/*
233 * routines to send LCP echos to peer
234 */
235
236static void lcp_echo_lowerup(ppp_pcb *pcb);
237static void lcp_echo_lowerdown(ppp_pcb *pcb);
238static void LcpEchoTimeout(void *arg);
239static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len);
240static void LcpSendEchoRequest(fsm *f);
241static void LcpLinkFailure(fsm *f);
242static void LcpEchoCheck(fsm *f);
243
244static 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
267static void lcp_init(ppp_pcb *pcb);
268static void lcp_input(ppp_pcb *pcb, u_char *p, int len);
269static void lcp_protrej(ppp_pcb *pcb);
270#if PRINTPKT_SUPPORT
271static int lcp_printpkt(const u_char *p, int plen,
272 void (*printer) (void *, const char *, ...), void *arg);
273#endif /* PRINTPKT_SUPPORT */
274
275const 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 */
326static int
327noopt(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
338static int
339setendpoint(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
350static void
351printendpoint(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 */
363static 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_MRU;
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 */
406void 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 */
422void 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 */
457void 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_DEFMRU, 0xffffffff, 0, 0) < 0
466 || ppp_recv_config(pcb, PPP_DEFMRU, (pcb->settings.lax_recv? 0: 0xffffffff),
467 wo->neg_pcompression, wo->neg_accompression) < 0)
468 return;
469 pcb->peer_mru = PPP_DEFMRU;
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 */
482void 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 */
496static 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 */
509static 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 */
523static 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 */
562static 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*/
620static 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 */
632void 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 */
651static 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_DEFMRU;
761#if 0 /* UNUSED */
762 auth_reset(pcb);
763#endif /* UNUSED */
764}
765
766
767/*
768 * lcp_cilen - Return length of our CI.
769 */
770static 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 */
834static 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 */
947static 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);
1112bad:
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 */
1127static 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 /* This is potentially dead code (#if !PPP_AUTH_SUPPORT)
1502 * Thus the double parantheses to mark the code explicitely
1503 * disabled when building with clang
1504 */
1505 if ((0
1506#if CHAP_SUPPORT
1507 || go->neg_chap || no.neg_chap
1508#endif /* CHAP_SUPPORT */
1509#if PAP_SUPPORT
1510 || go->neg_upap || no.neg_upap
1511#endif /* PAP_SUPPORT */
1512#if EAP_SUPPORT
1513 || go->neg_eap || no.neg_eap
1514#endif /* EAP_SUPPORT */
1515 ))
1516 goto bad;
1517 break;
1518 case CI_MAGICNUMBER:
1519 if (go->neg_magicnumber || no.neg_magicnumber ||
1520 cilen != CILEN_LONG)
1521 goto bad;
1522 break;
1523 case CI_PCOMPRESSION:
1524 if (go->neg_pcompression || no.neg_pcompression
1525 || cilen != CILEN_VOID)
1526 goto bad;
1527 break;
1528 case CI_ACCOMPRESSION:
1529 if (go->neg_accompression || no.neg_accompression
1530 || cilen != CILEN_VOID)
1531 goto bad;
1532 break;
1533#if LQR_SUPPORT
1534 case CI_QUALITY:
1535 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1536 goto bad;
1537 break;
1538#endif /* LQR_SUPPORT */
1539#ifdef HAVE_MULTILINK
1540 case CI_MRRU:
1541 if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1542 goto bad;
1543 break;
1544#endif /* HAVE_MULTILINK */
1545 case CI_SSNHF:
1546 if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1547 goto bad;
1548 try_.neg_ssnhf = 1;
1549 break;
1550 case CI_EPDISC:
1551 if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1552 goto bad;
1553 break;
1554 default:
1555 break;
1556 }
1557 p = next;
1558 }
1559
1560 /*
1561 * OK, the Nak is good. Now we can update state.
1562 * If there are any options left we ignore them.
1563 */
1564 if (f->state != PPP_FSM_OPENED) {
1565 if (looped_back) {
1566 if (++try_.numloops >= pcb->settings.lcp_loopbackfail) {
1567 ppp_notice(("Serial line is looped back."));
1568 pcb->err_code = PPPERR_LOOPBACK;
1569 lcp_close(f->pcb, "Loopback detected");
1570 }
1571 } else
1572 try_.numloops = 0;
1573 *go = try_;
1574 }
1575
1576 return 1;
1577
1578bad:
1579 LCPDEBUG(("lcp_nakci: received bad Nak!"));
1580 return 0;
1581}
1582
1583
1584/*
1585 * lcp_rejci - Peer has Rejected some of our CIs.
1586 * This should not modify any state if the Reject is bad
1587 * or if LCP is in the OPENED state.
1588 *
1589 * Returns:
1590 * 0 - Reject was bad.
1591 * 1 - Reject was good.
1592 */
1593static int lcp_rejci(fsm *f, u_char *p, int len) {
1594 ppp_pcb *pcb = f->pcb;
1595 lcp_options *go = &pcb->lcp_gotoptions;
1596 u_char cichar;
1597 u_short cishort;
1598 u32_t cilong;
1599 lcp_options try_; /* options to request next time */
1600
1601 try_ = *go;
1602
1603 /*
1604 * Any Rejected CIs must be in exactly the same order that we sent.
1605 * Check packet length and CI length at each step.
1606 * If we find any deviations, then this packet is bad.
1607 */
1608#define REJCIVOID(opt, neg) \
1609 if (go->neg && \
1610 len >= CILEN_VOID && \
1611 p[1] == CILEN_VOID && \
1612 p[0] == opt) { \
1613 len -= CILEN_VOID; \
1614 INCPTR(CILEN_VOID, p); \
1615 try_.neg = 0; \
1616 }
1617#define REJCISHORT(opt, neg, val) \
1618 if (go->neg && \
1619 len >= CILEN_SHORT && \
1620 p[1] == CILEN_SHORT && \
1621 p[0] == opt) { \
1622 len -= CILEN_SHORT; \
1623 INCPTR(2, p); \
1624 GETSHORT(cishort, p); \
1625 /* Check rejected value. */ \
1626 if (cishort != val) \
1627 goto bad; \
1628 try_.neg = 0; \
1629 }
1630
1631#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT
1632#define REJCICHAP(opt, neg, val) \
1633 if (go->neg && \
1634 len >= CILEN_CHAP && \
1635 p[1] == CILEN_CHAP && \
1636 p[0] == opt) { \
1637 len -= CILEN_CHAP; \
1638 INCPTR(2, p); \
1639 GETSHORT(cishort, p); \
1640 GETCHAR(cichar, p); \
1641 /* Check rejected value. */ \
1642 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1643 goto bad; \
1644 try_.neg = 0; \
1645 try_.neg_eap = try_.neg_upap = 0; \
1646 }
1647#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */
1648
1649#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT
1650#define REJCICHAP(opt, neg, val) \
1651 if (go->neg && \
1652 len >= CILEN_CHAP && \
1653 p[1] == CILEN_CHAP && \
1654 p[0] == opt) { \
1655 len -= CILEN_CHAP; \
1656 INCPTR(2, p); \
1657 GETSHORT(cishort, p); \
1658 GETCHAR(cichar, p); \
1659 /* Check rejected value. */ \
1660 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1661 goto bad; \
1662 try_.neg = 0; \
1663 try_.neg_upap = 0; \
1664 }
1665#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */
1666
1667#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT
1668#define REJCICHAP(opt, neg, val) \
1669 if (go->neg && \
1670 len >= CILEN_CHAP && \
1671 p[1] == CILEN_CHAP && \
1672 p[0] == opt) { \
1673 len -= CILEN_CHAP; \
1674 INCPTR(2, p); \
1675 GETSHORT(cishort, p); \
1676 GETCHAR(cichar, p); \
1677 /* Check rejected value. */ \
1678 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1679 goto bad; \
1680 try_.neg = 0; \
1681 try_.neg_eap = 0; \
1682 }
1683#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */
1684
1685#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT
1686#define REJCICHAP(opt, neg, val) \
1687 if (go->neg && \
1688 len >= CILEN_CHAP && \
1689 p[1] == CILEN_CHAP && \
1690 p[0] == opt) { \
1691 len -= CILEN_CHAP; \
1692 INCPTR(2, p); \
1693 GETSHORT(cishort, p); \
1694 GETCHAR(cichar, p); \
1695 /* Check rejected value. */ \
1696 if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
1697 goto bad; \
1698 try_.neg = 0; \
1699 }
1700#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */
1701
1702#define REJCILONG(opt, neg, val) \
1703 if (go->neg && \
1704 len >= CILEN_LONG && \
1705 p[1] == CILEN_LONG && \
1706 p[0] == opt) { \
1707 len -= CILEN_LONG; \
1708 INCPTR(2, p); \
1709 GETLONG(cilong, p); \
1710 /* Check rejected value. */ \
1711 if (cilong != val) \
1712 goto bad; \
1713 try_.neg = 0; \
1714 }
1715#if LQR_SUPPORT
1716#define REJCILQR(opt, neg, val) \
1717 if (go->neg && \
1718 len >= CILEN_LQR && \
1719 p[1] == CILEN_LQR && \
1720 p[0] == opt) { \
1721 len -= CILEN_LQR; \
1722 INCPTR(2, p); \
1723 GETSHORT(cishort, p); \
1724 GETLONG(cilong, p); \
1725 /* Check rejected value. */ \
1726 if (cishort != PPP_LQR || cilong != val) \
1727 goto bad; \
1728 try_.neg = 0; \
1729 }
1730#endif /* LQR_SUPPORT */
1731#define REJCICBCP(opt, neg, val) \
1732 if (go->neg && \
1733 len >= CILEN_CBCP && \
1734 p[1] == CILEN_CBCP && \
1735 p[0] == opt) { \
1736 len -= CILEN_CBCP; \
1737 INCPTR(2, p); \
1738 GETCHAR(cichar, p); \
1739 /* Check rejected value. */ \
1740 if (cichar != val) \
1741 goto bad; \
1742 try_.neg = 0; \
1743 }
1744#define REJCIENDP(opt, neg, class, val, vlen) \
1745 if (go->neg && \
1746 len >= CILEN_CHAR + vlen && \
1747 p[0] == opt && \
1748 p[1] == CILEN_CHAR + vlen) { \
1749 int i; \
1750 len -= CILEN_CHAR + vlen; \
1751 INCPTR(2, p); \
1752 GETCHAR(cichar, p); \
1753 if (cichar != class) \
1754 goto bad; \
1755 for (i = 0; i < vlen; ++i) { \
1756 GETCHAR(cichar, p); \
1757 if (cichar != val[i]) \
1758 goto bad; \
1759 } \
1760 try_.neg = 0; \
1761 }
1762
1763 REJCISHORT(CI_MRU, neg_mru, go->mru);
1764 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1765#if EAP_SUPPORT
1766 REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
1767 if (!go->neg_eap) {
1768#endif /* EAP_SUPPORT */
1769#if CHAP_SUPPORT
1770 REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
1771 if (!go->neg_chap) {
1772#endif /* CHAP_SUPPORT */
1773#if PAP_SUPPORT
1774 REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1775#endif /* PAP_SUPPORT */
1776#if CHAP_SUPPORT
1777 }
1778#endif /* CHAP_SUPPORT */
1779#if EAP_SUPPORT
1780 }
1781#endif /* EAP_SUPPORT */
1782#if LQR_SUPPORT
1783 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1784#endif /* LQR_SUPPORT */
1785 REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1786 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1787 REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1788 REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1789#ifdef HAVE_MULTILINK
1790 REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1791#endif /* HAVE_MULTILINK */
1792 REJCIVOID(CI_SSNHF, neg_ssnhf);
1793 REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_,
1794 go->endpoint.value, go->endpoint.length);
1795
1796 /*
1797 * If there are any remaining CIs, then this packet is bad.
1798 */
1799 if (len != 0)
1800 goto bad;
1801 /*
1802 * Now we can update state.
1803 */
1804 if (f->state != PPP_FSM_OPENED)
1805 *go = try_;
1806 return 1;
1807
1808bad:
1809 LCPDEBUG(("lcp_rejci: received bad Reject!"));
1810 return 0;
1811}
1812
1813
1814/*
1815 * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1816 *
1817 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1818 * appropriately. If reject_if_disagree is non-zero, doesn't return
1819 * CONFNAK; returns CONFREJ if it can't return CONFACK.
1820 *
1821 * inp = Requested CIs
1822 * lenp = Length of requested CIs
1823 */
1824static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) {
1825 ppp_pcb *pcb = f->pcb;
1826 lcp_options *go = &pcb->lcp_gotoptions;
1827 lcp_options *ho = &pcb->lcp_hisoptions;
1828 lcp_options *ao = &pcb->lcp_allowoptions;
1829 u_char *cip, *next; /* Pointer to current and next CIs */
1830 int cilen, citype, cichar; /* Parsed len, type, char value */
1831 u_short cishort; /* Parsed short value */
1832 u32_t cilong; /* Parse long value */
1833 int rc = CONFACK; /* Final packet return code */
1834 int orc; /* Individual option return code */
1835 u_char *p; /* Pointer to next char to parse */
1836 u_char *rejp; /* Pointer to next char in reject frame */
1837 struct pbuf *nakp; /* Nak buffer */
1838 u_char *nakoutp; /* Pointer to next char in Nak frame */
1839 int l = *lenp; /* Length left */
1840
1841 /*
1842 * Reset all his options.
1843 */
1844 BZERO(ho, sizeof(*ho));
1845
1846 /*
1847 * Process all his options.
1848 */
1849 next = inp;
1850 nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_UNKNOWN_SIZE), PBUF_RAM);
1851 if(NULL == nakp)
1852 return 0;
1853 if(nakp->tot_len != nakp->len) {
1854 pbuf_free(nakp);
1855 return 0;
1856 }
1857
1858 nakoutp = (u_char*)nakp->payload;
1859 rejp = inp;
1860 while (l) {
1861 orc = CONFACK; /* Assume success */
1862 cip = p = next; /* Remember beginning of CI */
1863 if (l < 2 || /* Not enough data for CI header or */
1864 p[1] < 2 || /* CI length too small or */
1865 p[1] > l) { /* CI length too big? */
1866 LCPDEBUG(("lcp_reqci: bad CI length!"));
1867 orc = CONFREJ; /* Reject bad CI */
1868 cilen = l; /* Reject till end of packet */
1869 l = 0; /* Don't loop again */
1870 citype = 0;
1871 goto endswitch;
1872 }
1873 GETCHAR(citype, p); /* Parse CI type */
1874 GETCHAR(cilen, p); /* Parse CI length */
1875 l -= cilen; /* Adjust remaining length */
1876 next += cilen; /* Step to next CI */
1877
1878 switch (citype) { /* Check CI type */
1879 case CI_MRU:
1880 if (!ao->neg_mru || /* Allow option? */
1881 cilen != CILEN_SHORT) { /* Check CI length */
1882 orc = CONFREJ; /* Reject CI */
1883 break;
1884 }
1885 GETSHORT(cishort, p); /* Parse MRU */
1886
1887 /*
1888 * He must be able to receive at least our minimum.
1889 * No need to check a maximum. If he sends a large number,
1890 * we'll just ignore it.
1891 */
1892 if (cishort < PPP_MINMRU) {
1893 orc = CONFNAK; /* Nak CI */
1894 PUTCHAR(CI_MRU, nakoutp);
1895 PUTCHAR(CILEN_SHORT, nakoutp);
1896 PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */
1897 break;
1898 }
1899 ho->neg_mru = 1; /* Remember he sent MRU */
1900 ho->mru = cishort; /* And remember value */
1901 break;
1902
1903 case CI_ASYNCMAP:
1904 if (!ao->neg_asyncmap ||
1905 cilen != CILEN_LONG) {
1906 orc = CONFREJ;
1907 break;
1908 }
1909 GETLONG(cilong, p);
1910
1911 /*
1912 * Asyncmap must have set at least the bits
1913 * which are set in lcp_allowoptions[unit].asyncmap.
1914 */
1915 if ((ao->asyncmap & ~cilong) != 0) {
1916 orc = CONFNAK;
1917 PUTCHAR(CI_ASYNCMAP, nakoutp);
1918 PUTCHAR(CILEN_LONG, nakoutp);
1919 PUTLONG(ao->asyncmap | cilong, nakoutp);
1920 break;
1921 }
1922 ho->neg_asyncmap = 1;
1923 ho->asyncmap = cilong;
1924 break;
1925
1926 case CI_AUTHTYPE:
1927 if (cilen < CILEN_SHORT ||
1928 !(0
1929#if PAP_SUPPORT
1930 || ao->neg_upap
1931#endif /* PAP_SUPPORT */
1932#if CHAP_SUPPORT
1933 || ao->neg_chap
1934#endif /* CHAP_SUPPORT */
1935#if EAP_SUPPORT
1936 || ao->neg_eap
1937#endif /* EAP_SUPPORT */
1938 )) {
1939 /*
1940 * Reject the option if we're not willing to authenticate.
1941 */
1942 ppp_dbglog(("No auth is possible"));
1943 orc = CONFREJ;
1944 break;
1945 }
1946 GETSHORT(cishort, p);
1947
1948 /*
1949 * Authtype must be PAP, CHAP, or EAP.
1950 *
1951 * Note: if more than one of ao->neg_upap, ao->neg_chap, and
1952 * ao->neg_eap are set, and the peer sends a Configure-Request
1953 * with two or more authenticate-protocol requests, then we will
1954 * reject the second request.
1955 * Whether we end up doing CHAP, UPAP, or EAP depends then on
1956 * the ordering of the CIs in the peer's Configure-Request.
1957 */
1958
1959#if PAP_SUPPORT
1960 if (cishort == PPP_PAP) {
1961 /* we've already accepted CHAP or EAP */
1962 if (0
1963#if CHAP_SUPPORT
1964 || ho->neg_chap
1965#endif /* CHAP_SUPPORT */
1966#if EAP_SUPPORT
1967 || ho->neg_eap
1968#endif /* EAP_SUPPORT */
1969 || cilen != CILEN_SHORT) {
1970 LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1971 orc = CONFREJ;
1972 break;
1973 }
1974 if (!ao->neg_upap) { /* we don't want to do PAP */
1975 orc = CONFNAK; /* NAK it and suggest CHAP or EAP */
1976 PUTCHAR(CI_AUTHTYPE, nakoutp);
1977#if EAP_SUPPORT
1978 if (ao->neg_eap) {
1979 PUTCHAR(CILEN_SHORT, nakoutp);
1980 PUTSHORT(PPP_EAP, nakoutp);
1981 } else {
1982#endif /* EAP_SUPPORT */
1983#if CHAP_SUPPORT
1984 PUTCHAR(CILEN_CHAP, nakoutp);
1985 PUTSHORT(PPP_CHAP, nakoutp);
1986 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
1987#endif /* CHAP_SUPPORT */
1988#if EAP_SUPPORT
1989 }
1990#endif /* EAP_SUPPORT */
1991 break;
1992 }
1993 ho->neg_upap = 1;
1994 break;
1995 }
1996#endif /* PAP_SUPPORT */
1997#if CHAP_SUPPORT
1998 if (cishort == PPP_CHAP) {
1999 /* we've already accepted PAP or EAP */
2000 if (
2001#if PAP_SUPPORT
2002 ho->neg_upap ||
2003#endif /* PAP_SUPPORT */
2004#if EAP_SUPPORT
2005 ho->neg_eap ||
2006#endif /* EAP_SUPPORT */
2007 cilen != CILEN_CHAP) {
2008 LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
2009 orc = CONFREJ;
2010 break;
2011 }
2012 if (!ao->neg_chap) { /* we don't want to do CHAP */
2013 orc = CONFNAK; /* NAK it and suggest EAP or PAP */
2014 PUTCHAR(CI_AUTHTYPE, nakoutp);
2015 PUTCHAR(CILEN_SHORT, nakoutp);
2016#if EAP_SUPPORT
2017 if (ao->neg_eap) {
2018 PUTSHORT(PPP_EAP, nakoutp);
2019 } else
2020#endif /* EAP_SUPPORT */
2021#if PAP_SUPPORT
2022 if(1) {
2023 PUTSHORT(PPP_PAP, nakoutp);
2024 }
2025 else
2026#endif /* PAP_SUPPORT */
2027 {}
2028 break;
2029 }
2030 GETCHAR(cichar, p); /* get digest type */
2031 if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) {
2032 /*
2033 * We can't/won't do the requested type,
2034 * suggest something else.
2035 */
2036 orc = CONFNAK;
2037 PUTCHAR(CI_AUTHTYPE, nakoutp);
2038 PUTCHAR(CILEN_CHAP, nakoutp);
2039 PUTSHORT(PPP_CHAP, nakoutp);
2040 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2041 break;
2042 }
2043 ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */
2044 ho->neg_chap = 1;
2045 break;
2046 }
2047#endif /* CHAP_SUPPORT */
2048#if EAP_SUPPORT
2049 if (cishort == PPP_EAP) {
2050 /* we've already accepted CHAP or PAP */
2051 if (
2052#if CHAP_SUPPORT
2053 ho->neg_chap ||
2054#endif /* CHAP_SUPPORT */
2055#if PAP_SUPPORT
2056 ho->neg_upap ||
2057#endif /* PAP_SUPPORT */
2058 cilen != CILEN_SHORT) {
2059 LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
2060 orc = CONFREJ;
2061 break;
2062 }
2063 if (!ao->neg_eap) { /* we don't want to do EAP */
2064 orc = CONFNAK; /* NAK it and suggest CHAP or PAP */
2065 PUTCHAR(CI_AUTHTYPE, nakoutp);
2066#if CHAP_SUPPORT
2067 if (ao->neg_chap) {
2068 PUTCHAR(CILEN_CHAP, nakoutp);
2069 PUTSHORT(PPP_CHAP, nakoutp);
2070 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2071 } else
2072#endif /* CHAP_SUPPORT */
2073#if PAP_SUPPORT
2074 if(1) {
2075 PUTCHAR(CILEN_SHORT, nakoutp);
2076 PUTSHORT(PPP_PAP, nakoutp);
2077 } else
2078#endif /* PAP_SUPPORT */
2079 {}
2080 break;
2081 }
2082 ho->neg_eap = 1;
2083 break;
2084 }
2085#endif /* EAP_SUPPORT */
2086
2087 /*
2088 * We don't recognize the protocol they're asking for.
2089 * Nak it with something we're willing to do.
2090 * (At this point we know ao->neg_upap || ao->neg_chap ||
2091 * ao->neg_eap.)
2092 */
2093 orc = CONFNAK;
2094 PUTCHAR(CI_AUTHTYPE, nakoutp);
2095
2096#if EAP_SUPPORT
2097 if (ao->neg_eap) {
2098 PUTCHAR(CILEN_SHORT, nakoutp);
2099 PUTSHORT(PPP_EAP, nakoutp);
2100 } else
2101#endif /* EAP_SUPPORT */
2102#if CHAP_SUPPORT
2103 if (ao->neg_chap) {
2104 PUTCHAR(CILEN_CHAP, nakoutp);
2105 PUTSHORT(PPP_CHAP, nakoutp);
2106 PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp);
2107 } else
2108#endif /* CHAP_SUPPORT */
2109#if PAP_SUPPORT
2110 if(1) {
2111 PUTCHAR(CILEN_SHORT, nakoutp);
2112 PUTSHORT(PPP_PAP, nakoutp);
2113 } else
2114#endif /* PAP_SUPPORT */
2115 {}
2116 break;
2117
2118#if LQR_SUPPORT
2119 case CI_QUALITY:
2120 if (!ao->neg_lqr ||
2121 cilen != CILEN_LQR) {
2122 orc = CONFREJ;
2123 break;
2124 }
2125
2126 GETSHORT(cishort, p);
2127 GETLONG(cilong, p);
2128
2129 /*
2130 * Check the protocol and the reporting period.
2131 * XXX When should we Nak this, and what with?
2132 */
2133 if (cishort != PPP_LQR) {
2134 orc = CONFNAK;
2135 PUTCHAR(CI_QUALITY, nakoutp);
2136 PUTCHAR(CILEN_LQR, nakoutp);
2137 PUTSHORT(PPP_LQR, nakoutp);
2138 PUTLONG(ao->lqr_period, nakoutp);
2139 break;
2140 }
2141 break;
2142#endif /* LQR_SUPPORT */
2143
2144 case CI_MAGICNUMBER:
2145 if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
2146 cilen != CILEN_LONG) {
2147 orc = CONFREJ;
2148 break;
2149 }
2150 GETLONG(cilong, p);
2151
2152 /*
2153 * He must have a different magic number.
2154 */
2155 if (go->neg_magicnumber &&
2156 cilong == go->magicnumber) {
2157 cilong = magic(); /* Don't put magic() inside macro! */
2158 orc = CONFNAK;
2159 PUTCHAR(CI_MAGICNUMBER, nakoutp);
2160 PUTCHAR(CILEN_LONG, nakoutp);
2161 PUTLONG(cilong, nakoutp);
2162 break;
2163 }
2164 ho->neg_magicnumber = 1;
2165 ho->magicnumber = cilong;
2166 break;
2167
2168
2169 case CI_PCOMPRESSION:
2170 if (!ao->neg_pcompression ||
2171 cilen != CILEN_VOID) {
2172 orc = CONFREJ;
2173 break;
2174 }
2175 ho->neg_pcompression = 1;
2176 break;
2177
2178 case CI_ACCOMPRESSION:
2179 if (!ao->neg_accompression ||
2180 cilen != CILEN_VOID) {
2181 orc = CONFREJ;
2182 break;
2183 }
2184 ho->neg_accompression = 1;
2185 break;
2186
2187#ifdef HAVE_MULTILINK
2188 case CI_MRRU:
2189 if (!ao->neg_mrru
2190 || !multilink
2191 || cilen != CILEN_SHORT) {
2192 orc = CONFREJ;
2193 break;
2194 }
2195
2196 GETSHORT(cishort, p);
2197 /* possibly should insist on a minimum/maximum MRRU here */
2198 ho->neg_mrru = 1;
2199 ho->mrru = cishort;
2200 break;
2201#endif /* HAVE_MULTILINK */
2202
2203 case CI_SSNHF:
2204 if (!ao->neg_ssnhf
2205#ifdef HAVE_MULTILINK
2206 || !multilink
2207#endif /* HAVE_MULTILINK */
2208 || cilen != CILEN_VOID) {
2209 orc = CONFREJ;
2210 break;
2211 }
2212 ho->neg_ssnhf = 1;
2213 break;
2214
2215 case CI_EPDISC:
2216 if (!ao->neg_endpoint ||
2217 cilen < CILEN_CHAR ||
2218 cilen > CILEN_CHAR + MAX_ENDP_LEN) {
2219 orc = CONFREJ;
2220 break;
2221 }
2222 GETCHAR(cichar, p);
2223 cilen -= CILEN_CHAR;
2224 ho->neg_endpoint = 1;
2225 ho->endpoint.class_ = cichar;
2226 ho->endpoint.length = cilen;
2227 MEMCPY(ho->endpoint.value, p, cilen);
2228 INCPTR(cilen, p);
2229 break;
2230
2231 default:
2232 LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
2233 orc = CONFREJ;
2234 break;
2235 }
2236
2237endswitch:
2238 if (orc == CONFACK && /* Good CI */
2239 rc != CONFACK) /* but prior CI wasn't? */
2240 continue; /* Don't send this one */
2241
2242 if (orc == CONFNAK) { /* Nak this CI? */
2243 if (reject_if_disagree /* Getting fed up with sending NAKs? */
2244 && citype != CI_MAGICNUMBER) {
2245 orc = CONFREJ; /* Get tough if so */
2246 } else {
2247 if (rc == CONFREJ) /* Rejecting prior CI? */
2248 continue; /* Don't send this one */
2249 rc = CONFNAK;
2250 }
2251 }
2252 if (orc == CONFREJ) { /* Reject this CI */
2253 rc = CONFREJ;
2254 if (cip != rejp) /* Need to move rejected CI? */
2255 MEMCPY(rejp, cip, cilen); /* Move it */
2256 INCPTR(cilen, rejp); /* Update output pointer */
2257 }
2258 }
2259
2260 /*
2261 * If we wanted to send additional NAKs (for unsent CIs), the
2262 * code would go here. The extra NAKs would go at *nakoutp.
2263 * At present there are no cases where we want to ask the
2264 * peer to negotiate an option.
2265 */
2266
2267 switch (rc) {
2268 case CONFACK:
2269 *lenp = next - inp;
2270 break;
2271 case CONFNAK:
2272 /*
2273 * Copy the Nak'd options from the nak buffer to the caller's buffer.
2274 */
2275 *lenp = nakoutp - (u_char*)nakp->payload;
2276 MEMCPY(inp, nakp->payload, *lenp);
2277 break;
2278 case CONFREJ:
2279 *lenp = rejp - inp;
2280 break;
2281 default:
2282 break;
2283 }
2284
2285 pbuf_free(nakp);
2286 LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
2287 return (rc); /* Return final code */
2288}
2289
2290
2291/*
2292 * lcp_up - LCP has come UP.
2293 */
2294static void lcp_up(fsm *f) {
2295 ppp_pcb *pcb = f->pcb;
2296 lcp_options *wo = &pcb->lcp_wantoptions;
2297 lcp_options *ho = &pcb->lcp_hisoptions;
2298 lcp_options *go = &pcb->lcp_gotoptions;
2299 lcp_options *ao = &pcb->lcp_allowoptions;
2300 int mtu, mru;
2301
2302 if (!go->neg_magicnumber)
2303 go->magicnumber = 0;
2304 if (!ho->neg_magicnumber)
2305 ho->magicnumber = 0;
2306
2307 /*
2308 * Set our MTU to the smaller of the MTU we wanted and
2309 * the MRU our peer wanted. If we negotiated an MRU,
2310 * set our MRU to the larger of value we wanted and
2311 * the value we got in the negotiation.
2312 * Note on the MTU: the link MTU can be the MRU the peer wanted,
2313 * the interface MTU is set to the lowest of that, the
2314 * MTU we want to use, and our link MRU.
2315 */
2316 mtu = ho->neg_mru? ho->mru: PPP_DEFMRU;
2317 mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_DEFMRU;
2318#ifdef HAVE_MULTILINK
2319 if (!(multilink && go->neg_mrru && ho->neg_mrru))
2320#endif /* HAVE_MULTILINK */
2321 ppp_netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru));
2322 ppp_send_config(pcb, mtu,
2323 (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
2324 ho->neg_pcompression, ho->neg_accompression);
2325 ppp_recv_config(pcb, mru,
2326 (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
2327 go->neg_pcompression, go->neg_accompression);
2328
2329 if (ho->neg_mru)
2330 pcb->peer_mru = ho->mru;
2331
2332 lcp_echo_lowerup(f->pcb); /* Enable echo messages */
2333
2334 link_established(pcb);
2335}
2336
2337
2338/*
2339 * lcp_down - LCP has gone DOWN.
2340 *
2341 * Alert other protocols.
2342 */
2343static void lcp_down(fsm *f) {
2344 ppp_pcb *pcb = f->pcb;
2345 lcp_options *go = &pcb->lcp_gotoptions;
2346
2347 lcp_echo_lowerdown(f->pcb);
2348
2349 link_down(pcb);
2350
2351 ppp_send_config(pcb, PPP_DEFMRU, 0xffffffff, 0, 0);
2352 ppp_recv_config(pcb, PPP_DEFMRU,
2353 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
2354 go->neg_pcompression, go->neg_accompression);
2355 pcb->peer_mru = PPP_DEFMRU;
2356}
2357
2358
2359/*
2360 * lcp_starting - LCP needs the lower layer up.
2361 */
2362static void lcp_starting(fsm *f) {
2363 ppp_pcb *pcb = f->pcb;
2364 link_required(pcb);
2365}
2366
2367
2368/*
2369 * lcp_finished - LCP has finished with the lower layer.
2370 */
2371static void lcp_finished(fsm *f) {
2372 ppp_pcb *pcb = f->pcb;
2373 link_terminated(pcb);
2374}
2375
2376
2377#if PRINTPKT_SUPPORT
2378/*
2379 * lcp_printpkt - print the contents of an LCP packet.
2380 */
2381static const char* const lcp_codenames[] = {
2382 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
2383 "TermReq", "TermAck", "CodeRej", "ProtRej",
2384 "EchoReq", "EchoRep", "DiscReq", "Ident",
2385 "TimeRem"
2386};
2387
2388static int lcp_printpkt(const u_char *p, int plen,
2389 void (*printer) (void *, const char *, ...), void *arg) {
2390 int code, id, len, olen, i;
2391 const u_char *pstart, *optend;
2392 u_short cishort;
2393 u32_t cilong;
2394
2395 if (plen < HEADERLEN)
2396 return 0;
2397 pstart = p;
2398 GETCHAR(code, p);
2399 GETCHAR(id, p);
2400 GETSHORT(len, p);
2401 if (len < HEADERLEN || len > plen)
2402 return 0;
2403
2404 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames))
2405 printer(arg, " %s", lcp_codenames[code-1]);
2406 else
2407 printer(arg, " code=0x%x", code);
2408 printer(arg, " id=0x%x", id);
2409 len -= HEADERLEN;
2410 switch (code) {
2411 case CONFREQ:
2412 case CONFACK:
2413 case CONFNAK:
2414 case CONFREJ:
2415 /* print option list */
2416 while (len >= 2) {
2417 GETCHAR(code, p);
2418 GETCHAR(olen, p);
2419 p -= 2;
2420 if (olen < 2 || olen > len) {
2421 break;
2422 }
2423 printer(arg, " <");
2424 len -= olen;
2425 optend = p + olen;
2426 switch (code) {
2427 case CI_MRU:
2428 if (olen == CILEN_SHORT) {
2429 p += 2;
2430 GETSHORT(cishort, p);
2431 printer(arg, "mru %d", cishort);
2432 }
2433 break;
2434 case CI_ASYNCMAP:
2435 if (olen == CILEN_LONG) {
2436 p += 2;
2437 GETLONG(cilong, p);
2438 printer(arg, "asyncmap 0x%x", cilong);
2439 }
2440 break;
2441 case CI_AUTHTYPE:
2442 if (olen >= CILEN_SHORT) {
2443 p += 2;
2444 printer(arg, "auth ");
2445 GETSHORT(cishort, p);
2446 switch (cishort) {
2447#if PAP_SUPPORT
2448 case PPP_PAP:
2449 printer(arg, "pap");
2450 break;
2451#endif /* PAP_SUPPORT */
2452#if CHAP_SUPPORT
2453 case PPP_CHAP:
2454 printer(arg, "chap");
2455 if (p < optend) {
2456 switch (*p) {
2457 case CHAP_MD5:
2458 printer(arg, " MD5");
2459 ++p;
2460 break;
2461#if MSCHAP_SUPPORT
2462 case CHAP_MICROSOFT:
2463 printer(arg, " MS");
2464 ++p;
2465 break;
2466
2467 case CHAP_MICROSOFT_V2:
2468 printer(arg, " MS-v2");
2469 ++p;
2470 break;
2471#endif /* MSCHAP_SUPPORT */
2472 default:
2473 break;
2474 }
2475 }
2476 break;
2477#endif /* CHAP_SUPPORT */
2478#if EAP_SUPPORT
2479 case PPP_EAP:
2480 printer(arg, "eap");
2481 break;
2482#endif /* EAP_SUPPORT */
2483 default:
2484 printer(arg, "0x%x", cishort);
2485 }
2486 }
2487 break;
2488#if LQR_SUPPORT
2489 case CI_QUALITY:
2490 if (olen >= CILEN_SHORT) {
2491 p += 2;
2492 printer(arg, "quality ");
2493 GETSHORT(cishort, p);
2494 switch (cishort) {
2495 case PPP_LQR:
2496 printer(arg, "lqr");
2497 break;
2498 default:
2499 printer(arg, "0x%x", cishort);
2500 }
2501 }
2502 break;
2503#endif /* LQR_SUPPORT */
2504 case CI_CALLBACK:
2505 if (olen >= CILEN_CHAR) {
2506 p += 2;
2507 printer(arg, "callback ");
2508 GETCHAR(cishort, p);
2509 switch (cishort) {
2510 case CBCP_OPT:
2511 printer(arg, "CBCP");
2512 break;
2513 default:
2514 printer(arg, "0x%x", cishort);
2515 }
2516 }
2517 break;
2518 case CI_MAGICNUMBER:
2519 if (olen == CILEN_LONG) {
2520 p += 2;
2521 GETLONG(cilong, p);
2522 printer(arg, "magic 0x%x", cilong);
2523 }
2524 break;
2525 case CI_PCOMPRESSION:
2526 if (olen == CILEN_VOID) {
2527 p += 2;
2528 printer(arg, "pcomp");
2529 }
2530 break;
2531 case CI_ACCOMPRESSION:
2532 if (olen == CILEN_VOID) {
2533 p += 2;
2534 printer(arg, "accomp");
2535 }
2536 break;
2537 case CI_MRRU:
2538 if (olen == CILEN_SHORT) {
2539 p += 2;
2540 GETSHORT(cishort, p);
2541 printer(arg, "mrru %d", cishort);
2542 }
2543 break;
2544 case CI_SSNHF:
2545 if (olen == CILEN_VOID) {
2546 p += 2;
2547 printer(arg, "ssnhf");
2548 }
2549 break;
2550 case CI_EPDISC:
2551#ifdef HAVE_MULTILINK
2552 if (olen >= CILEN_CHAR) {
2553 struct epdisc epd;
2554 p += 2;
2555 GETCHAR(epd.class, p);
2556 epd.length = olen - CILEN_CHAR;
2557 if (epd.length > MAX_ENDP_LEN)
2558 epd.length = MAX_ENDP_LEN;
2559 if (epd.length > 0) {
2560 MEMCPY(epd.value, p, epd.length);
2561 p += epd.length;
2562 }
2563 printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
2564 }
2565#else
2566 printer(arg, "endpoint");
2567#endif
2568 break;
2569 default:
2570 break;
2571 }
2572 while (p < optend) {
2573 GETCHAR(code, p);
2574 printer(arg, " %.2x", code);
2575 }
2576 printer(arg, ">");
2577 }
2578 break;
2579
2580 case TERMACK:
2581 case TERMREQ:
2582 if (len > 0 && *p >= ' ' && *p < 0x7f) {
2583 printer(arg, " ");
2584 ppp_print_string(p, len, printer, arg);
2585 p += len;
2586 len = 0;
2587 }
2588 break;
2589
2590 case ECHOREQ:
2591 case ECHOREP:
2592 case DISCREQ:
2593 if (len >= 4) {
2594 GETLONG(cilong, p);
2595 printer(arg, " magic=0x%x", cilong);
2596 len -= 4;
2597 }
2598 break;
2599
2600 case IDENTIF:
2601 case TIMEREM:
2602 if (len >= 4) {
2603 GETLONG(cilong, p);
2604 printer(arg, " magic=0x%x", cilong);
2605 len -= 4;
2606 }
2607 if (code == TIMEREM) {
2608 if (len < 4)
2609 break;
2610 GETLONG(cilong, p);
2611 printer(arg, " seconds=%u", cilong);
2612 len -= 4;
2613 }
2614 if (len > 0) {
2615 printer(arg, " ");
2616 ppp_print_string(p, len, printer, arg);
2617 p += len;
2618 len = 0;
2619 }
2620 break;
2621 default:
2622 break;
2623 }
2624
2625 /* print the rest of the bytes in the packet */
2626 for (i = 0; i < len && i < 32; ++i) {
2627 GETCHAR(code, p);
2628 printer(arg, " %.2x", code);
2629 }
2630 if (i < len) {
2631 printer(arg, " ...");
2632 p += len - i;
2633 }
2634
2635 return p - pstart;
2636}
2637#endif /* PRINTPKT_SUPPORT */
2638
2639/*
2640 * Time to shut down the link because there is nothing out there.
2641 */
2642
2643static void LcpLinkFailure(fsm *f) {
2644 ppp_pcb *pcb = f->pcb;
2645 if (f->state == PPP_FSM_OPENED) {
2646 ppp_info(("No response to %d echo-requests", pcb->lcp_echos_pending));
2647 ppp_notice(("Serial link appears to be disconnected."));
2648 pcb->err_code = PPPERR_PEERDEAD;
2649 lcp_close(pcb, "Peer not responding");
2650 }
2651}
2652
2653/*
2654 * Timer expired for the LCP echo requests from this process.
2655 */
2656
2657static void LcpEchoCheck(fsm *f) {
2658 ppp_pcb *pcb = f->pcb;
2659
2660 LcpSendEchoRequest (f);
2661 if (f->state != PPP_FSM_OPENED)
2662 return;
2663
2664 /*
2665 * Start the timer for the next interval.
2666 */
2667 if (pcb->lcp_echo_timer_running)
2668 ppp_warn(("assertion lcp_echo_timer_running==0 failed"));
2669 TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval);
2670 pcb->lcp_echo_timer_running = 1;
2671}
2672
2673/*
2674 * LcpEchoTimeout - Timer expired on the LCP echo
2675 */
2676
2677static void LcpEchoTimeout(void *arg) {
2678 fsm *f = (fsm*)arg;
2679 ppp_pcb *pcb = f->pcb;
2680 if (pcb->lcp_echo_timer_running != 0) {
2681 pcb->lcp_echo_timer_running = 0;
2682 LcpEchoCheck ((fsm *) arg);
2683 }
2684}
2685
2686/*
2687 * LcpEchoReply - LCP has received a reply to the echo
2688 */
2689
2690static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) {
2691 ppp_pcb *pcb = f->pcb;
2692 lcp_options *go = &pcb->lcp_gotoptions;
2693 u32_t magic_val;
2694 LWIP_UNUSED_ARG(id);
2695
2696 /* Check the magic number - don't count replies from ourselves. */
2697 if (len < 4) {
2698 ppp_dbglog(("lcp: received short Echo-Reply, length %d", len));
2699 return;
2700 }
2701 GETLONG(magic_val, inp);
2702 if (go->neg_magicnumber
2703 && magic_val == go->magicnumber) {
2704 ppp_warn(("appear to have received our own echo-reply!"));
2705 return;
2706 }
2707
2708 /* Reset the number of outstanding echo frames */
2709 pcb->lcp_echos_pending = 0;
2710}
2711
2712/*
2713 * LcpSendEchoRequest - Send an echo request frame to the peer
2714 */
2715
2716static void LcpSendEchoRequest(fsm *f) {
2717 ppp_pcb *pcb = f->pcb;
2718 lcp_options *go = &pcb->lcp_gotoptions;
2719 u32_t lcp_magic;
2720 u_char pkt[4], *pktp;
2721
2722 /*
2723 * Detect the failure of the peer at this point.
2724 */
2725 if (pcb->settings.lcp_echo_fails != 0) {
2726 if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) {
2727 LcpLinkFailure(f);
2728 pcb->lcp_echos_pending = 0;
2729 }
2730 }
2731
2732#if PPP_LCP_ADAPTIVE
2733 /*
2734 * If adaptive echos have been enabled, only send the echo request if
2735 * no traffic was received since the last one.
2736 */
2737 if (pcb->settings.lcp_echo_adaptive) {
2738 static unsigned int last_pkts_in = 0;
2739
2740#if PPP_STATS_SUPPORT
2741 update_link_stats(f->unit);
2742 link_stats_valid = 0;
2743#endif /* PPP_STATS_SUPPORT */
2744
2745 if (link_stats.pkts_in != last_pkts_in) {
2746 last_pkts_in = link_stats.pkts_in;
2747 return;
2748 }
2749 }
2750#endif
2751
2752 /*
2753 * Make and send the echo request frame.
2754 */
2755 if (f->state == PPP_FSM_OPENED) {
2756 lcp_magic = go->magicnumber;
2757 pktp = pkt;
2758 PUTLONG(lcp_magic, pktp);
2759 fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt);
2760 ++pcb->lcp_echos_pending;
2761 }
2762}
2763
2764/*
2765 * lcp_echo_lowerup - Start the timer for the LCP frame
2766 */
2767
2768static void lcp_echo_lowerup(ppp_pcb *pcb) {
2769 fsm *f = &pcb->lcp_fsm;
2770
2771 /* Clear the parameters for generating echo frames */
2772 pcb->lcp_echos_pending = 0;
2773 pcb->lcp_echo_number = 0;
2774 pcb->lcp_echo_timer_running = 0;
2775
2776 /* If a timeout interval is specified then start the timer */
2777 if (pcb->settings.lcp_echo_interval != 0)
2778 LcpEchoCheck (f);
2779}
2780
2781/*
2782 * lcp_echo_lowerdown - Stop the timer for the LCP frame
2783 */
2784
2785static void lcp_echo_lowerdown(ppp_pcb *pcb) {
2786 fsm *f = &pcb->lcp_fsm;
2787
2788 if (pcb->lcp_echo_timer_running != 0) {
2789 UNTIMEOUT (LcpEchoTimeout, f);
2790 pcb->lcp_echo_timer_running = 0;
2791 }
2792}
2793
2794#endif /* PPP_SUPPORT */
#define U(x)
Definition: wordpad.c:45
struct protocol * protocols
Definition: dispatch.c:56
r l[0]
Definition: byte_order.h:168
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define LWIP_MAX(x, y)
Definition: def.h:65
#define LWIP_ARRAYSIZE(x)
Definition: def.h:69
#define LWIP_MIN(x, y)
Definition: def.h:66
UINT32 u_int
Definition: types.h:82
#define NULL
Definition: types.h:112
unsigned short u_short
Definition: types.h:81
UCHAR u_char
Definition: types.h:80
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
GLenum pname
Definition: glext.h:5645
GLfloat f
Definition: glext.h:7540
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
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
uint32_t u32_t
Definition: arch.h:129
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_RAW
Definition: pbuf.h:111
if(dx< 0)
Definition: linetemp.h:194
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
const char * optend(char *fmt) const
Definition: mkisofs.c:1691
#define argv
Definition: mplay32.c:18
#define TIMEOUT
Definition: ntpclient.c:12
static unsigned __int64 next
Definition: rand_nt.c:6
Definition: inflate.c:139
Definition: nis.h:10
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
u16_t len
Definition: pbuf.h:203
void * payload
Definition: pbuf.h:191
#define LOG_DEBUG
Definition: syslog.h:52
void * arg
Definition: msvc.h:10