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