lcp.c revision 33063
1/* 2 * PPP Link Control Protocol (LCP) Module 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id: lcp.c,v 1.55 1998/01/21 02:15:18 brian Exp $ 21 * 22 * TODO: 23 * o Validate magic number received from peer. 24 * o Limit data field length by MRU 25 */ 26#include <sys/param.h> 27#include <sys/time.h> 28#include <sys/socket.h> 29#include <net/if.h> 30#include <net/if_tun.h> 31#include <netinet/in.h> 32#include <arpa/inet.h> 33 34#include <signal.h> 35#include <stdarg.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <sys/time.h> 40#include <termios.h> 41#include <unistd.h> 42 43#include "command.h" 44#include "mbuf.h" 45#include "log.h" 46#include "defs.h" 47#include "timer.h" 48#include "fsm.h" 49#include "lcp.h" 50#include "ipcp.h" 51#include "lcpproto.h" 52#include "os.h" 53#include "hdlc.h" 54#include "ccp.h" 55#include "lqr.h" 56#include "phase.h" 57#include "loadalias.h" 58#include "vars.h" 59#include "auth.h" 60#include "pap.h" 61#include "chap.h" 62#include "async.h" 63#include "main.h" 64#include "ip.h" 65#include "modem.h" 66#include "tun.h" 67 68/* for received LQRs */ 69struct lqrreq { 70 u_char type; 71 u_char length; 72 u_short proto; /* Quality protocol */ 73 u_long period; /* Reporting interval */ 74}; 75 76struct lcpstate LcpInfo; 77 78static void LcpSendConfigReq(struct fsm *); 79static void LcpSendTerminateReq(struct fsm *); 80static void LcpSendTerminateAck(struct fsm *); 81static void LcpDecodeConfig(u_char *, int, int); 82static void LcpInitRestartCounter(struct fsm *); 83static void LcpLayerUp(struct fsm *); 84static void LcpLayerDown(struct fsm *); 85static void LcpLayerStart(struct fsm *); 86static void LcpLayerFinish(struct fsm *); 87 88static const char *cftypes[] = { 89 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 90 "???", 91 "MRU", /* 1: Maximum-Receive-Unit */ 92 "ACCMAP", /* 2: Async-Control-Character-Map */ 93 "AUTHPROTO", /* 3: Authentication-Protocol */ 94 "QUALPROTO", /* 4: Quality-Protocol */ 95 "MAGICNUM", /* 5: Magic-Number */ 96 "RESERVED", /* 6: RESERVED */ 97 "PROTOCOMP", /* 7: Protocol-Field-Compression */ 98 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */ 99 "FCSALT", /* 9: FCS-Alternatives */ 100 "SDP", /* 10: Self-Describing-Pad */ 101 "NUMMODE", /* 11: Numbered-Mode */ 102 "MULTIPROC", /* 12: Multi-Link-Procedure */ 103 "CALLBACK", /* 13: Callback */ 104 "CONTIME", /* 14: Connect-Time */ 105 "COMPFRAME", /* 15: Compound-Frames */ 106 "NDE", /* 16: Nominal-Data-Encapsulation */ 107 "MULTIMRRU", /* 17: Multilink-MRRU */ 108 "MULTISSNH", /* 18: Multilink-Short-Sequence-Number-Header */ 109 "MULTIED", /* 19: Multilink-Endpoint-Descriminator */ 110 "PROPRIETRY", /* 20: Proprietary */ 111 "DCEID", /* 21: DCE-Identifier */ 112 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */ 113 "LDBACP", /* 23: Link Discriminator for BACP */ 114}; 115 116#define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 117 118struct fsm LcpFsm = { 119 "LCP", /* Name of protocol */ 120 PROTO_LCP, /* Protocol Number */ 121 LCP_MAXCODE, 122 1, /* Open mode delay */ 123 ST_INITIAL, /* State of machine */ 124 0, 0, 0, 125 {0, 0, 0, NULL, NULL, NULL}, /* FSM timer */ 126 {0, 0, 0, NULL, NULL, NULL}, /* Open timer */ 127 {0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */ 128 LogLCP, 129 130 LcpLayerUp, 131 LcpLayerDown, 132 LcpLayerStart, 133 LcpLayerFinish, 134 LcpInitRestartCounter, 135 LcpSendConfigReq, 136 LcpSendTerminateReq, 137 LcpSendTerminateAck, 138 LcpDecodeConfig, 139}; 140 141static struct pppTimer LcpReportTimer; 142static int LcpFailedMagic; 143 144static void 145LcpReportTime(void *data) 146{ 147 if (LogIsKept(LogDEBUG)) { 148 time_t t; 149 150 time(&t); 151 LogPrintf(LogDEBUG, "LcpReportTime: %s\n", ctime(&t)); 152 } 153 StopTimer(&LcpReportTimer); 154 LcpReportTimer.state = TIMER_STOPPED; 155 StartTimer(&LcpReportTimer); 156 HdlcErrorCheck(); 157} 158 159int 160ReportLcpStatus(struct cmdargs const *arg) 161{ 162 struct lcpstate *lcp = &LcpInfo; 163 struct fsm *fp = &LcpFsm; 164 165 if (!VarTerm) 166 return 1; 167 168 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]); 169 fprintf(VarTerm, 170 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d,\n" 171 " MAGIC %08lx, REJECT %04x\n", 172 lcp->his_mru, (u_long)lcp->his_accmap, lcp->his_protocomp, 173 lcp->his_acfcomp, (u_long)lcp->his_magic, lcp->his_reject); 174 fprintf(VarTerm, 175 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d,\n" 176 " MAGIC %08lx, REJECT %04x\n", 177 lcp->want_mru, (u_long)lcp->want_accmap, lcp->want_protocomp, 178 lcp->want_acfcomp, (u_long)lcp->want_magic, lcp->my_reject); 179 fprintf(VarTerm, "\nDefaults: MRU = %d, ACCMAP = %08lx\t", 180 VarMRU, (u_long)VarAccmap); 181 fprintf(VarTerm, "Open Mode: %s", 182 (VarOpenMode == OPEN_PASSIVE) ? "passive" : "active"); 183 if (VarOpenMode > 0) 184 fprintf(VarTerm, " (delay %d)", VarOpenMode); 185 fputc('\n', VarTerm); 186 return 0; 187} 188 189/* 190 * Generate random number which will be used as magic number. 191 */ 192static u_int32_t 193GenerateMagic(void) 194{ 195 randinit(); 196 return (random()); 197} 198 199void 200LcpInit() 201{ 202 struct lcpstate *lcp = &LcpInfo; 203 204 FsmInit(&LcpFsm); 205 HdlcInit(); 206 207 memset(lcp, '\0', sizeof(struct lcpstate)); 208 lcp->want_mru = VarMRU; 209 lcp->his_mru = DEF_MRU; 210 lcp->his_accmap = 0xffffffff; 211 lcp->want_accmap = VarAccmap; 212 lcp->want_magic = GenerateMagic(); 213 lcp->want_auth = lcp->his_auth = 0; 214 if (Enabled(ConfChap)) 215 lcp->want_auth = PROTO_CHAP; 216 else if (Enabled(ConfPap)) 217 lcp->want_auth = PROTO_PAP; 218 if (Enabled(ConfLqr)) 219 lcp->want_lqrperiod = VarLqrTimeout * 100; 220 if (Enabled(ConfAcfcomp)) 221 lcp->want_acfcomp = 1; 222 if (Enabled(ConfProtocomp)) 223 lcp->want_protocomp = 1; 224 LcpFsm.maxconfig = 10; 225} 226 227static void 228LcpInitRestartCounter(struct fsm * fp) 229{ 230 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 231 fp->restart = 5; 232} 233 234int 235LcpPutConf(int log, u_char *tgt, const struct lcp_opt *o, const char *nm, 236 const char *arg, ...) 237{ 238 va_list ap; 239 char buf[30]; 240 241 va_start(ap, arg); 242 memcpy(tgt, o, o->len); 243 if (arg == NULL || *arg == '\0') 244 LogPrintf(log, " %s[%d]\n", nm, o->len); 245 else { 246 vsnprintf(buf, sizeof buf, arg, ap); 247 LogPrintf(log, " %s[%d] %s\n", nm, o->len, buf); 248 } 249 va_end(ap); 250 251 return o->len; 252} 253 254#define PUTN(ty) \ 255do { \ 256 o.id = ty; \ 257 o.len = 2; \ 258 cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], NULL); \ 259} while (0) 260 261#define PUTHEX32(ty, arg) \ 262do { \ 263 o.id = ty; \ 264 o.len = 6; \ 265 *(u_long *)o.data = htonl(arg); \ 266 cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], "0x%08lx", (u_long)arg);\ 267} while (0) 268 269#define PUTACCMAP(arg) PUTHEX32(TY_ACCMAP, arg) 270#define PUTMAGIC(arg) PUTHEX32(TY_MAGICNUM, arg) 271 272#define PUTMRU(arg) \ 273do { \ 274 o.id = TY_MRU; \ 275 o.len = 4; \ 276 *(u_short *)o.data = htons(arg); \ 277 cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], "%u", arg); \ 278} while (0) 279 280#define PUTLQR(period) \ 281do { \ 282 o.id = TY_QUALPROTO; \ 283 o.len = 8; \ 284 *(u_short *)o.data = htons(PROTO_LQR); \ 285 *(u_long *)(o.data+2) = htonl(period); \ 286 cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \ 287 "period %ld", (u_long)period); \ 288} while (0) 289 290#define PUTPAP() \ 291do { \ 292 o.id = TY_AUTHPROTO; \ 293 o.len = 4; \ 294 *(u_short *)o.data = htons(PROTO_PAP); \ 295 cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \ 296 "0x%04x (PAP)", PROTO_PAP); \ 297} while (0) 298 299#define PUTCHAP(val) \ 300do { \ 301 o.id = TY_AUTHPROTO; \ 302 o.len = 5; \ 303 *(u_short *)o.data = htons(PROTO_CHAP); \ 304 o.data[2] = val; \ 305 cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \ 306 "0x%04x (CHAP 0x%02x)", PROTO_CHAP, val); \ 307} while (0) 308 309#define PUTMD5CHAP() PUTCHAP(0x05) 310#define PUTMSCHAP() PUTCHAP(0x80) 311 312static void 313LcpSendConfigReq(struct fsm * fp) 314{ 315 u_char *cp; 316 struct lcpstate *lcp = &LcpInfo; 317 struct lcp_opt o; 318 319 LogPrintf(LogLCP, "LcpSendConfigReq\n"); 320 cp = ReqBuff; 321 if (!DEV_IS_SYNC) { 322 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) 323 PUTN(TY_ACFCOMP); 324 325 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) 326 PUTN(TY_PROTOCOMP); 327 328 if (!REJECTED(lcp, TY_ACCMAP)) 329 PUTACCMAP(lcp->want_accmap); 330 } 331 332 if (!REJECTED(lcp, TY_MRU)) 333 PUTMRU(lcp->want_mru); 334 335 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) 336 PUTMAGIC(lcp->want_magic); 337 338 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) 339 PUTLQR(lcp->want_lqrperiod); 340 341 switch (lcp->want_auth) { 342 case PROTO_PAP: 343 PUTPAP(); 344 break; 345 346 case PROTO_CHAP: 347#ifdef HAVE_DES 348 if (VarMSChap) 349 PUTMSCHAP(); /* Use MSChap */ 350 else 351#endif 352 PUTMD5CHAP(); /* Use MD5 */ 353 break; 354 } 355 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 356} 357 358void 359LcpSendProtoRej(u_char * option, int count) 360{ 361 struct fsm *fp = &LcpFsm; 362 363 LogPrintf(LogLCP, "LcpSendProtoRej\n"); 364 FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count); 365} 366 367static void 368LcpSendTerminateReq(struct fsm * fp) 369{ 370 /* Most thins are done in fsm layer. Nothing to to. */ 371} 372 373static void 374LcpSendTerminateAck(struct fsm * fp) 375{ 376 LogPrintf(LogLCP, "LcpSendTerminateAck.\n"); 377 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 378} 379 380static void 381LcpLayerStart(struct fsm * fp) 382{ 383 LogPrintf(LogLCP, "LcpLayerStart\n"); 384 NewPhase(PHASE_ESTABLISH); 385} 386 387static void 388StopAllTimers(void) 389{ 390 StopTimer(&LcpReportTimer); 391 StopIdleTimer(); 392 StopTimer(&AuthPapInfo.authtimer); 393 StopTimer(&AuthChapInfo.authtimer); 394 StopLqrTimer(); 395} 396 397static void 398LcpLayerFinish(struct fsm * fp) 399{ 400 LogPrintf(LogLCP, "LcpLayerFinish\n"); 401 HangupModem(0); 402 StopAllTimers(); 403 /* We're down at last. Lets tell background and direct mode to get out */ 404 NewPhase(PHASE_DEAD); 405 LcpInit(); 406 IpcpInit(); 407 CcpInit(); 408 Prompt(); 409} 410 411static void 412LcpLayerUp(struct fsm * fp) 413{ 414 LogPrintf(LogLCP, "LcpLayerUp\n"); 415 tun_configure(LcpInfo.his_mru, ModemSpeed()); 416 SetLinkParams(&LcpInfo); 417 418 NewPhase(PHASE_AUTHENTICATE); 419 420 StartLqm(); 421 StopTimer(&LcpReportTimer); 422 LcpReportTimer.state = TIMER_STOPPED; 423 LcpReportTimer.load = 60 * SECTICKS; 424 LcpReportTimer.func = LcpReportTime; 425 StartTimer(&LcpReportTimer); 426} 427 428static void 429LcpLayerDown(struct fsm * fp) 430{ 431 StopAllTimers(); 432 OsLinkdown(); 433 LogPrintf(LogLCP, "LcpLayerDown\n"); 434 /* 435 * OsLinkdown() brings CCP & IPCP down, then waits 'till we go from 436 * STOPPING to STOPPED. At this point, the FSM gives us a LayerFinish 437 */ 438} 439 440void 441LcpUp() 442{ 443 FsmUp(&LcpFsm); 444 LcpFailedMagic = 0; 445} 446 447void 448LcpDown() 449{ /* Sudden death */ 450 LcpFailedMagic = 0; 451 FsmDown(&LcpFsm); 452 /* FsmDown() results in a LcpLayerDown() if we're currently open. */ 453 LcpLayerFinish(&LcpFsm); 454} 455 456void 457LcpOpen(int open_mode) 458{ 459 LcpFsm.open_mode = open_mode; 460 LcpFailedMagic = 0; 461 FsmOpen(&LcpFsm); 462} 463 464void 465LcpClose() 466{ 467 NewPhase(PHASE_TERMINATE); 468 OsInterfaceDown(0); 469 FsmClose(&LcpFsm); 470 LcpFailedMagic = 0; 471} 472 473/* 474 * XXX: Should validate option length 475 */ 476static void 477LcpDecodeConfig(u_char *cp, int plen, int mode_type) 478{ 479 int type, length, sz, pos; 480 u_int32_t *lp, magic, accmap; 481 u_short mtu, mru, *sp, proto; 482 struct lqrreq *req; 483 char request[20], desc[22]; 484 485 ackp = AckBuff; 486 nakp = NakBuff; 487 rejp = RejBuff; 488 489 while (plen >= sizeof(struct fsmconfig)) { 490 type = *cp; 491 length = cp[1]; 492 493 if (type < 0 || type >= NCFTYPES) 494 snprintf(request, sizeof request, " <%d>[%d]", type, length); 495 else 496 snprintf(request, sizeof request, " %s[%d]", cftypes[type], length); 497 498 switch (type) { 499 case TY_MRU: 500 sp = (u_short *) (cp + 2); 501 mru = htons(*sp); 502 LogPrintf(LogLCP, "%s %d\n", request, mru); 503 504 switch (mode_type) { 505 case MODE_REQ: 506 mtu = VarPrefMTU; 507 if (mtu == 0) 508 mtu = MAX_MTU; 509 if (mru > mtu) { 510 *sp = htons(mtu); 511 memcpy(nakp, cp, 4); 512 nakp += 4; 513 } else if (mru < MIN_MRU) { 514 *sp = htons(MIN_MRU); 515 memcpy(nakp, cp, 4); 516 nakp += 4; 517 } else { 518 LcpInfo.his_mru = mru; 519 memcpy(ackp, cp, 4); 520 ackp += 4; 521 } 522 break; 523 case MODE_NAK: 524 if (mru >= MIN_MRU || mru <= MAX_MRU) 525 LcpInfo.want_mru = mru; 526 break; 527 case MODE_REJ: 528 LcpInfo.his_reject |= (1 << type); 529 break; 530 } 531 break; 532 533 case TY_ACCMAP: 534 lp = (u_int32_t *) (cp + 2); 535 accmap = htonl(*lp); 536 LogPrintf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap); 537 538 switch (mode_type) { 539 case MODE_REQ: 540 LcpInfo.his_accmap = accmap; 541 memcpy(ackp, cp, 6); 542 ackp += 6; 543 break; 544 case MODE_NAK: 545 LcpInfo.want_accmap = accmap; 546 break; 547 case MODE_REJ: 548 LcpInfo.his_reject |= (1 << type); 549 break; 550 } 551 break; 552 553 case TY_AUTHPROTO: 554 sp = (u_short *) (cp + 2); 555 proto = ntohs(*sp); 556 switch (proto) { 557 case PROTO_PAP: 558 LogPrintf(LogLCP, "%s 0x%04x (PAP)\n", request, proto); 559 break; 560 case PROTO_CHAP: 561 LogPrintf(LogLCP, "%s 0x%04x (CHAP 0x%02x)\n", request, proto, cp[4]); 562 break; 563 default: 564 LogPrintf(LogLCP, "%s 0x%04x\n", request, proto); 565 break; 566 } 567 568 switch (mode_type) { 569 case MODE_REQ: 570 switch (proto) { 571 case PROTO_PAP: 572 if (length != 4) { 573 LogPrintf(LogLCP, " Bad length!\n"); 574 goto reqreject; 575 } 576 if (Acceptable(ConfPap)) { 577 LcpInfo.his_auth = proto; 578 memcpy(ackp, cp, length); 579 ackp += length; 580 } else if (Acceptable(ConfChap)) { 581 *nakp++ = *cp; 582 *nakp++ = 5; 583 *nakp++ = (unsigned char) (PROTO_CHAP >> 8); 584 *nakp++ = (unsigned char) PROTO_CHAP; 585#ifdef HAVE_DES 586 if (VarMSChap) 587 *nakp++ = 0x80; 588 else 589#endif 590 *nakp++ = 5; 591 } else 592 goto reqreject; 593 break; 594 595 case PROTO_CHAP: 596 if (length < 5) { 597 LogPrintf(LogLCP, " Bad length!\n"); 598 goto reqreject; 599 } 600#ifdef HAVE_DES 601 if (Acceptable(ConfChap) && (cp[4] == 5 || cp[4] == 0x80)) 602#else 603 if (Acceptable(ConfChap) && cp[4] == 5) 604#endif 605 { 606 LcpInfo.his_auth = proto; 607 memcpy(ackp, cp, length); 608 ackp += length; 609#ifdef HAVE_DES 610 VarMSChap = cp[4] == 0x80; 611#endif 612 } else if (Acceptable(ConfPap)) { 613 *nakp++ = *cp; 614 *nakp++ = 4; 615 *nakp++ = (unsigned char) (PROTO_PAP >> 8); 616 *nakp++ = (unsigned char) PROTO_PAP; 617 } else 618 goto reqreject; 619 break; 620 621 default: 622 LogPrintf(LogLCP, "%s 0x%04x - not recognised, NAK\n", 623 request, proto); 624 memcpy(nakp, cp, length); 625 nakp += length; 626 break; 627 } 628 break; 629 case MODE_NAK: 630 switch (proto) { 631 case PROTO_PAP: 632 if (Enabled(ConfPap)) 633 LcpInfo.want_auth = PROTO_PAP; 634 else { 635 LogPrintf(LogLCP, "Peer will only send PAP (not enabled)\n"); 636 LcpInfo.his_reject |= (1 << type); 637 } 638 break; 639 case PROTO_CHAP: 640 if (Enabled(ConfChap)) 641 LcpInfo.want_auth = PROTO_CHAP; 642 else { 643 LogPrintf(LogLCP, "Peer will only send CHAP (not enabled)\n"); 644 LcpInfo.his_reject |= (1 << type); 645 } 646 break; 647 default: 648 /* We've been NAK'd with something we don't understand :-( */ 649 LcpInfo.his_reject |= (1 << type); 650 break; 651 } 652 break; 653 case MODE_REJ: 654 LcpInfo.his_reject |= (1 << type); 655 break; 656 } 657 break; 658 659 case TY_QUALPROTO: 660 req = (struct lqrreq *) cp; 661 LogPrintf(LogLCP, "%s proto %x, interval %dms\n", 662 request, ntohs(req->proto), ntohl(req->period) * 10); 663 switch (mode_type) { 664 case MODE_REQ: 665 if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr)) 666 goto reqreject; 667 else { 668 LcpInfo.his_lqrperiod = ntohl(req->period); 669 if (LcpInfo.his_lqrperiod < 500) 670 LcpInfo.his_lqrperiod = 500; 671 req->period = htonl(LcpInfo.his_lqrperiod); 672 memcpy(ackp, cp, length); 673 ackp += length; 674 } 675 break; 676 case MODE_NAK: 677 break; 678 case MODE_REJ: 679 LcpInfo.his_reject |= (1 << type); 680 break; 681 } 682 break; 683 684 case TY_MAGICNUM: 685 lp = (u_int32_t *) (cp + 2); 686 magic = ntohl(*lp); 687 LogPrintf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic); 688 689 switch (mode_type) { 690 case MODE_REQ: 691 if (LcpInfo.want_magic) { 692 /* Validate magic number */ 693 if (magic == LcpInfo.want_magic) { 694 LogPrintf(LogLCP, "Magic is same (%08lx) - %d times\n", 695 (u_long)magic, ++LcpFailedMagic); 696 LcpInfo.want_magic = GenerateMagic(); 697 memcpy(nakp, cp, 6); 698 nakp += 6; 699 ualarm(TICKUNIT * (4 + 4 * LcpFailedMagic), 0); 700 sigpause(0); 701 } else { 702 LcpInfo.his_magic = magic; 703 memcpy(ackp, cp, length); 704 ackp += length; 705 LcpFailedMagic = 0; 706 } 707 } else { 708 LcpInfo.my_reject |= (1 << type); 709 goto reqreject; 710 } 711 break; 712 case MODE_NAK: 713 LogPrintf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic); 714 LcpInfo.want_magic = GenerateMagic(); 715 break; 716 case MODE_REJ: 717 LogPrintf(LogLCP, " Magic 0x%08x is REJected!\n", magic); 718 LcpInfo.want_magic = 0; 719 LcpInfo.his_reject |= (1 << type); 720 break; 721 } 722 break; 723 724 case TY_PROTOCOMP: 725 LogPrintf(LogLCP, "%s\n", request); 726 727 switch (mode_type) { 728 case MODE_REQ: 729 if (Acceptable(ConfProtocomp)) { 730 LcpInfo.his_protocomp = 1; 731 memcpy(ackp, cp, 2); 732 ackp += 2; 733 } else { 734#ifdef OLDMST 735 /* 736 * MorningStar before v1.3 needs NAK 737 */ 738 memcpy(nakp, cp, 2); 739 nakp += 2; 740#else 741 memcpy(rejp, cp, 2); 742 rejp += 2; 743 LcpInfo.my_reject |= (1 << type); 744#endif 745 } 746 break; 747 case MODE_NAK: 748 case MODE_REJ: 749 LcpInfo.want_protocomp = 0; 750 LcpInfo.his_reject |= (1 << type); 751 break; 752 } 753 break; 754 755 case TY_ACFCOMP: 756 LogPrintf(LogLCP, "%s\n", request); 757 switch (mode_type) { 758 case MODE_REQ: 759 if (Acceptable(ConfAcfcomp)) { 760 LcpInfo.his_acfcomp = 1; 761 memcpy(ackp, cp, 2); 762 ackp += 2; 763 } else { 764#ifdef OLDMST 765 /* 766 * MorningStar before v1.3 needs NAK 767 */ 768 memcpy(nakp, cp, 2); 769 nakp += 2; 770#else 771 memcpy(rejp, cp, 2); 772 rejp += 2; 773 LcpInfo.my_reject |= (1 << type); 774#endif 775 } 776 break; 777 case MODE_NAK: 778 case MODE_REJ: 779 LcpInfo.want_acfcomp = 0; 780 LcpInfo.his_reject |= (1 << type); 781 break; 782 } 783 break; 784 785 case TY_SDP: 786 LogPrintf(LogLCP, "%s\n", request); 787 switch (mode_type) { 788 case MODE_REQ: 789 case MODE_NAK: 790 case MODE_REJ: 791 break; 792 } 793 break; 794 795 default: 796 sz = (sizeof desc - 2) / 2; 797 if (sz > length - 2) 798 sz = length - 2; 799 pos = 0; 800 desc[0] = sz ? ' ' : '\0'; 801 for (pos = 0; sz--; pos++) 802 sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]); 803 804 LogPrintf(LogLCP, "%s%s\n", request, desc); 805 806 if (mode_type == MODE_REQ) { 807reqreject: 808 if (length > sizeof RejBuff - (rejp - RejBuff)) { 809 length = sizeof RejBuff - (rejp - RejBuff); 810 LogPrintf(LogLCP, "Can't REJ length %d - trunating to %d\n", 811 cp[1], length); 812 } 813 memcpy(rejp, cp, length); 814 rejp += length; 815 LcpInfo.my_reject |= (1 << type); 816 if (length != cp[1]) 817 return; 818 } 819 break; 820 } 821 /* to avoid inf. loop */ 822 if (length == 0) { 823 LogPrintf(LogLCP, "LCP size zero\n"); 824 break; 825 } 826 plen -= length; 827 cp += length; 828 } 829} 830 831void 832LcpInput(struct mbuf * bp) 833{ 834 FsmInput(&LcpFsm, bp); 835} 836