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