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_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 */ 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_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 */ 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_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 */ 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 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 1574bad: 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 */ 1589static 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 1804bad: 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 */ 1820static 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 2233endswitch: 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 */ 2290static 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 */ 2339static 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 */ 2358static 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 */ 2367static 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 */ 2377static const char* const lcp_codenames[] = { 2378 "ConfReq", "ConfAck", "ConfNak", "ConfRej", 2379 "TermReq", "TermAck", "CodeRej", "ProtRej", 2380 "EchoReq", "EchoRep", "DiscReq", "Ident", 2381 "TimeRem" 2382}; 2383 2384static 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 2639static 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 2653static 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 2673static 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 2686static 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 2712static 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 2764static 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 2781static 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 */ 2791