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