60#include "modem.h" 61 62struct lcpstate LcpInfo; 63 64static void LcpSendConfigReq(struct fsm *); 65static void LcpSendTerminateReq(struct fsm *); 66static void LcpSendTerminateAck(struct fsm *); 67static void LcpDecodeConfig(u_char *, int, int); 68static void LcpInitRestartCounter(struct fsm *); 69static void LcpLayerUp(struct fsm *); 70static void LcpLayerDown(struct fsm *); 71static void LcpLayerStart(struct fsm *); 72static void LcpLayerFinish(struct fsm *); 73 74#define REJECTED(p, x) (p->his_reject & (1<<x)) 75 76static char *cftypes[] = { 77 "???", "MRU", "ACCMAP", "AUTHPROTO", "QUALPROTO", "MAGICNUM", 78 "RESERVED", "PROTOCOMP", "ACFCOMP", "FCSALT", "SDP", 79}; 80 81struct fsm LcpFsm = { 82 "LCP", /* Name of protocol */ 83 PROTO_LCP, /* Protocol Number */ 84 LCP_MAXCODE, 85 OPEN_ACTIVE, 86 ST_INITIAL, /* State of machine */ 87 0, 0, 0, 88 0, 89 {0, 0, 0, NULL, NULL, NULL}, 90 {0, 0, 0, NULL, NULL, NULL}, 91 LogLCP, 92 93 LcpLayerUp, 94 LcpLayerDown, 95 LcpLayerStart, 96 LcpLayerFinish, 97 LcpInitRestartCounter, 98 LcpSendConfigReq, 99 LcpSendTerminateReq, 100 LcpSendTerminateAck, 101 LcpDecodeConfig, 102}; 103 104static struct pppTimer LcpReportTimer; 105static int LcpFailedMagic; 106 107static void 108LcpReportTime() 109{ 110 if (LogIsKept(LogDEBUG)) { 111 time_t t; 112 113 time(&t); 114 LogPrintf(LogDEBUG, "LcpReportTime: %s\n", ctime(&t)); 115 } 116 StopTimer(&LcpReportTimer); 117 LcpReportTimer.state = TIMER_STOPPED; 118 StartTimer(&LcpReportTimer); 119 HdlcErrorCheck(); 120} 121 122int 123ReportLcpStatus() 124{ 125 struct lcpstate *lcp = &LcpInfo; 126 struct fsm *fp = &LcpFsm; 127 128 if (!VarTerm) 129 return 1; 130 131 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]); 132 fprintf(VarTerm, 133 " his side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n" 134 " REJECT %04lx\n", 135 lcp->his_mru, lcp->his_accmap, lcp->his_protocomp, lcp->his_acfcomp, 136 lcp->his_magic, lcp->his_reject); 137 fprintf(VarTerm, 138 " my side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n" 139 " REJECT %04lx\n", 140 lcp->want_mru, lcp->want_accmap, lcp->want_protocomp, lcp->want_acfcomp, 141 lcp->want_magic, lcp->my_reject); 142 fprintf(VarTerm, "\nDefaults: MRU = %ld, ACCMAP = %08x\t", VarMRU, VarAccmap); 143 fprintf(VarTerm, "Open Mode: %s\n", (VarOpenMode == OPEN_ACTIVE) ? "active" : "passive"); 144 return 0; 145} 146 147/* 148 * Generate random number which will be used as magic number. 149 */ 150static u_long 151GenerateMagic() 152{ 153 randinit(); 154 return (random()); 155} 156 157void 158LcpInit() 159{ 160 struct lcpstate *lcp = &LcpInfo; 161 162 FsmInit(&LcpFsm); 163 HdlcInit(); 164 165 memset(lcp, '\0', sizeof(struct lcpstate)); 166 lcp->want_mru = VarMRU; 167 lcp->his_mru = DEF_MRU; 168 lcp->his_accmap = 0xffffffff; 169 lcp->want_accmap = VarAccmap; 170 lcp->want_magic = GenerateMagic(); 171 lcp->want_auth = lcp->his_auth = 0; 172 if (Enabled(ConfChap)) 173 lcp->want_auth = PROTO_CHAP; 174 else if (Enabled(ConfPap)) 175 lcp->want_auth = PROTO_PAP; 176 if (Enabled(ConfLqr)) 177 lcp->want_lqrperiod = VarLqrTimeout * 100; 178 if (Enabled(ConfAcfcomp)) 179 lcp->want_acfcomp = 1; 180 if (Enabled(ConfProtocomp)) 181 lcp->want_protocomp = 1; 182 LcpFsm.maxconfig = 10; 183} 184 185static void 186LcpInitRestartCounter(struct fsm * fp) 187{ 188 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 189 fp->restart = 5; 190} 191 192void 193PutConfValue(u_char ** cpp, char **types, u_char type, int len, u_long val) 194{ 195 u_char *cp; 196 struct in_addr ina; 197 198 cp = *cpp; 199 *cp++ = type; 200 *cp++ = len; 201 if (len == 6) { 202 if (type == TY_IPADDR) { 203 ina.s_addr = htonl(val); 204 LogPrintf(LogLCP, " %s [%d] %s\n", 205 types[type], len, inet_ntoa(ina)); 206 } else { 207 LogPrintf(LogLCP, " %s [%d] %08x\n", types[type], len, val); 208 } 209 *cp++ = (val >> 24) & 0377; 210 *cp++ = (val >> 16) & 0377; 211 } else 212 LogPrintf(LogLCP, " %s [%d] %d\n", types[type], len, val); 213 *cp++ = (val >> 8) & 0377; 214 *cp++ = val & 0377; 215 *cpp = cp; 216} 217 218static void 219LcpSendConfigReq(struct fsm * fp) 220{ 221 u_char *cp; 222 struct lcpstate *lcp = &LcpInfo; 223 struct lqrreq *req; 224 225 LogPrintf(LogLCP, "LcpSendConfigReq\n"); 226 cp = ReqBuff; 227 if (!DEV_IS_SYNC) { 228 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) { 229 *cp++ = TY_ACFCOMP; 230 *cp++ = 2; 231 LogPrintf(LogLCP, " %s\n", cftypes[TY_ACFCOMP]); 232 } 233 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) { 234 *cp++ = TY_PROTOCOMP; 235 *cp++ = 2; 236 LogPrintf(LogLCP, " %s\n", cftypes[TY_PROTOCOMP]); 237 } 238 if (!REJECTED(lcp, TY_ACCMAP)) 239 PutConfValue(&cp, cftypes, TY_ACCMAP, 6, lcp->want_accmap); 240 } 241 if (!REJECTED(lcp, TY_MRU)) 242 PutConfValue(&cp, cftypes, TY_MRU, 4, lcp->want_mru); 243 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) 244 PutConfValue(&cp, cftypes, TY_MAGICNUM, 6, lcp->want_magic); 245 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) { 246 req = (struct lqrreq *) cp; 247 req->type = TY_QUALPROTO; 248 req->length = sizeof(struct lqrreq); 249 req->proto = htons(PROTO_LQR); 250 req->period = htonl(lcp->want_lqrperiod); 251 cp += sizeof(struct lqrreq); 252 LogPrintf(LogLCP, " %s (%d)\n", cftypes[TY_QUALPROTO], lcp->want_lqrperiod); 253 } 254 switch (lcp->want_auth) { 255 case PROTO_PAP: 256 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 4, lcp->want_auth); 257 break; 258 case PROTO_CHAP: 259 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 5, lcp->want_auth); 260#ifdef HAVE_DES 261 *cp++ = VarMSChap ? 0x80 : 0x05; /* Use MSChap vs. RFC 1994 (MD5) */ 262#else 263 *cp++ = 0x05; /* Use MD5 */ 264#endif 265 break; 266 } 267 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 268} 269 270void 271LcpSendProtoRej(u_char * option, int count) 272{ 273 struct fsm *fp = &LcpFsm; 274 275 LogPrintf(LogLCP, "LcpSendProtoRej\n"); 276 FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count); 277} 278 279static void 280LcpSendTerminateReq(struct fsm * fp) 281{ 282 /* Most thins are done in fsm layer. Nothing to to. */ 283} 284 285static void 286LcpSendTerminateAck(struct fsm * fp) 287{ 288 LogPrintf(LogLCP, "LcpSendTerminateAck.\n"); 289 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 290} 291 292static void 293LcpLayerStart(struct fsm * fp) 294{ 295 LogPrintf(LogLCP, "LcpLayerStart\n"); 296 NewPhase(PHASE_ESTABLISH); 297} 298 299static void 300StopAllTimers() 301{ 302 StopTimer(&LcpReportTimer); 303 StopTimer(&IpcpReportTimer); 304 StopIdleTimer(); 305 StopTimer(&AuthPapInfo.authtimer); 306 StopTimer(&AuthChapInfo.authtimer); 307 StopLqrTimer(); 308} 309 310static void 311LcpLayerFinish(struct fsm * fp) 312{ 313 LogPrintf(LogLCP, "LcpLayerFinish\n"); 314 OsCloseLink(1); 315 NewPhase(PHASE_DEAD); 316 StopAllTimers(); 317 (void) OsInterfaceDown(0); 318 /* We're down at last. Lets tell background and direct mode to get out */ 319 NewPhase(PHASE_TERMINATE); 320 LcpInit(); 321 IpcpInit(); 322 CcpInit(); 323 Prompt(); 324} 325 326static void 327LcpLayerUp(struct fsm * fp) 328{ 329 LogPrintf(LogLCP, "LcpLayerUp\n"); 330 OsSetInterfaceParams(23, LcpInfo.his_mru, ModemSpeed()); 331 SetLinkParams(&LcpInfo); 332 333 NewPhase(PHASE_AUTHENTICATE); 334 335 StartLqm(); 336 StopTimer(&LcpReportTimer); 337 LcpReportTimer.state = TIMER_STOPPED; 338 LcpReportTimer.load = 60 * SECTICKS; 339 LcpReportTimer.func = LcpReportTime; 340 StartTimer(&LcpReportTimer); 341} 342 343static void 344LcpLayerDown(struct fsm * fp) 345{ 346 StopAllTimers(); 347 OsLinkdown(); 348 LogPrintf(LogLCP, "LcpLayerDown\n"); 349 /* 350 * OsLinkdown() brings CCP & IPCP down, then waits 'till we go from 351 * STOPPING to STOPPED. At this point, the FSM gives us a LayerFinish 352 */ 353} 354 355void 356LcpUp() 357{ 358 FsmUp(&LcpFsm); 359 LcpFailedMagic = 0; 360} 361 362void 363LcpDown() 364{ /* Sudden death */ 365 LcpFailedMagic = 0; 366 NewPhase(PHASE_DEAD); 367 StopAllTimers(); 368 FsmDown(&LcpFsm); 369 /* 370 * We now wait for the FsmDown() to result in a LcpLayerDown() (if we're 371 * open). 372 */ 373} 374 375void 376LcpOpen(int mode) 377{ 378 LcpFsm.open_mode = mode; 379 LcpFailedMagic = 0; 380 FsmOpen(&LcpFsm); 381} 382 383void 384LcpClose() 385{ 386 FsmClose(&LcpFsm); 387 LcpFailedMagic = 0; 388} 389 390/* 391 * XXX: Should validate option length 392 */ 393static void 394LcpDecodeConfig(u_char * cp, int plen, int mode) 395{ 396 char *request; 397 int type, length, mru, mtu; 398 u_long *lp, magic, accmap; 399 u_short *sp, proto; 400 struct lqrreq *req; 401 402 ackp = AckBuff; 403 nakp = NakBuff; 404 rejp = RejBuff; 405 406 while (plen >= sizeof(struct fsmconfig)) { 407 type = *cp; 408 length = cp[1]; 409 if (type <= TY_ACFCOMP) 410 request = cftypes[type]; 411 else 412 request = "???"; 413 414 switch (type) { 415 case TY_MRU: 416 sp = (u_short *) (cp + 2); 417 mru = htons(*sp); 418 LogPrintf(LogLCP, " %s %d\n", request, mru); 419 420 switch (mode) { 421 case MODE_REQ: 422 mtu = VarPrefMTU; 423 if (mtu == 0) 424 mtu = MAX_MTU; 425 if (mru > mtu) { 426 *sp = htons(mtu); 427 memcpy(nakp, cp, 4); 428 nakp += 4; 429 } else if (mru < MIN_MRU) { 430 *sp = htons(MIN_MRU); 431 memcpy(nakp, cp, 4); 432 nakp += 4; 433 } else { 434 LcpInfo.his_mru = mru; 435 memcpy(ackp, cp, 4); 436 ackp += 4; 437 } 438 break; 439 case MODE_NAK: 440 if (mru >= MIN_MRU || mru <= MAX_MRU) 441 LcpInfo.want_mru = mru; 442 break; 443 case MODE_REJ: 444 LcpInfo.his_reject |= (1 << type); 445 break; 446 } 447 break; 448 case TY_ACCMAP: 449 lp = (u_long *) (cp + 2); 450 accmap = htonl(*lp); 451 LogPrintf(LogLCP, " %s %08x\n", request, accmap); 452 453 switch (mode) { 454 case MODE_REQ: 455 LcpInfo.his_accmap = accmap; 456 memcpy(ackp, cp, 6); 457 ackp += 6; 458 break; 459 case MODE_NAK: 460 LcpInfo.want_accmap = accmap; 461 break; 462 case MODE_REJ: 463 LcpInfo.his_reject |= (1 << type); 464 break; 465 } 466 break; 467 case TY_AUTHPROTO: 468 sp = (u_short *) (cp + 2); 469 proto = ntohs(*sp); 470 LogPrintf(LogLCP, " %s proto = %04x\n", request, proto); 471 472 switch (mode) { 473 case MODE_REQ: 474 switch (proto) { 475 case PROTO_PAP: 476 if (length != 4) { 477 LogPrintf(LogLCP, " %s bad length (%d)\n", request, length); 478 goto reqreject; 479 } 480 if (Acceptable(ConfPap)) { 481 LcpInfo.his_auth = proto; 482 memcpy(ackp, cp, length); 483 ackp += length; 484 } else if (Acceptable(ConfChap)) { 485 *nakp++ = *cp; 486 *nakp++ = 5; 487 *nakp++ = (unsigned char) (PROTO_CHAP >> 8); 488 *nakp++ = (unsigned char) PROTO_CHAP; 489 *nakp++ = 5; 490 } else 491 goto reqreject; 492 break; 493 case PROTO_CHAP: 494 if (length < 5) { 495 LogPrintf(LogLCP, " %s bad length (%d)\n", request, length); 496 goto reqreject; 497 } 498#ifdef HAVE_DES 499 if (Acceptable(ConfChap) && (cp[4] == 5 || cp[4] == 0x80)) 500#else 501 if (Acceptable(ConfChap) && cp[4] == 5) 502#endif 503 { 504 LcpInfo.his_auth = proto; 505 memcpy(ackp, cp, length); 506 ackp += length; 507#ifdef HAVE_DES 508 VarMSChap = cp[4] = 0x80; 509#endif 510 } else if (Acceptable(ConfPap)) { 511 *nakp++ = *cp; 512 *nakp++ = 4; 513 *nakp++ = (unsigned char) (PROTO_PAP >> 8); 514 *nakp++ = (unsigned char) PROTO_PAP; 515 } else 516 goto reqreject; 517 break; 518 default: 519 LogPrintf(LogLCP, " %s not implemented, NAK.\n", request); 520 memcpy(nakp, cp, length); 521 nakp += length; 522 break; 523 } 524 break; 525 case MODE_NAK: 526 break; 527 case MODE_REJ: 528 LcpInfo.his_reject |= (1 << type); 529 break; 530 } 531 break; 532 case TY_QUALPROTO: 533 req = (struct lqrreq *) cp; 534 LogPrintf(LogLCP, " %s proto: %x, interval: %dms\n", 535 request, ntohs(req->proto), ntohl(req->period) * 10); 536 switch (mode) { 537 case MODE_REQ: 538 if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr)) 539 goto reqreject; 540 else { 541 LcpInfo.his_lqrperiod = ntohl(req->period); 542 if (LcpInfo.his_lqrperiod < 500) 543 LcpInfo.his_lqrperiod = 500; 544 req->period = htonl(LcpInfo.his_lqrperiod); 545 memcpy(ackp, cp, length); 546 ackp += length; 547 } 548 break; 549 case MODE_NAK: 550 break; 551 case MODE_REJ: 552 LcpInfo.his_reject |= (1 << type); 553 break; 554 } 555 break; 556 case TY_MAGICNUM: 557 lp = (u_long *) (cp + 2); 558 magic = ntohl(*lp); 559 LogPrintf(LogLCP, " %s %08x\n", request, magic); 560 561 switch (mode) { 562 case MODE_REQ: 563 if (LcpInfo.want_magic) { 564 /* Validate magic number */ 565 if (magic == LcpInfo.want_magic) { 566 LogPrintf(LogLCP, "Magic is same (%08x) - %d times\n", 567 magic, ++LcpFailedMagic); 568 LcpInfo.want_magic = GenerateMagic(); 569 memcpy(nakp, cp, 6); 570 nakp += 6; 571 ualarm(TICKUNIT * (4 + 4 * LcpFailedMagic), 0); 572 sigpause(0); 573 } else { 574 LcpInfo.his_magic = magic; 575 memcpy(ackp, cp, length); 576 ackp += length; 577 LcpFailedMagic = 0; 578 } 579 } else { 580 LcpInfo.my_reject |= (1 << type); 581 goto reqreject; 582 } 583 break; 584 case MODE_NAK: 585 LogPrintf(LogLCP, " %s magic %08x has NAKed\n", request, magic); 586 LcpInfo.want_magic = GenerateMagic(); 587 break; 588 case MODE_REJ: 589 LogPrintf(LogLCP, " %s magic has REJected\n", request); 590 LcpInfo.want_magic = 0; 591 LcpInfo.his_reject |= (1 << type); 592 break; 593 } 594 break; 595 case TY_PROTOCOMP: 596 LogPrintf(LogLCP, " %s\n", request); 597 598 switch (mode) { 599 case MODE_REQ: 600 if (Acceptable(ConfProtocomp)) { 601 LcpInfo.his_protocomp = 1; 602 memcpy(ackp, cp, 2); 603 ackp += 2; 604 } else { 605#ifdef OLDMST 606 /* 607 * MorningStar before v1.3 needs NAK 608 */ 609 memcpy(nakp, cp, 2); 610 nakp += 2; 611#else 612 memcpy(rejp, cp, 2); 613 rejp += 2; 614 LcpInfo.my_reject |= (1 << type); 615#endif 616 } 617 break; 618 case MODE_NAK: 619 case MODE_REJ: 620 LcpInfo.want_protocomp = 0; 621 LcpInfo.his_reject |= (1 << type); 622 break; 623 } 624 break; 625 case TY_ACFCOMP: 626 LogPrintf(LogLCP, " %s\n", request); 627 switch (mode) { 628 case MODE_REQ: 629 if (Acceptable(ConfAcfcomp)) { 630 LcpInfo.his_acfcomp = 1; 631 memcpy(ackp, cp, 2); 632 ackp += 2; 633 } else { 634#ifdef OLDMST 635 /* 636 * MorningStar before v1.3 needs NAK 637 */ 638 memcpy(nakp, cp, 2); 639 nakp += 2; 640#else 641 memcpy(rejp, cp, 2); 642 rejp += 2; 643 LcpInfo.my_reject |= (1 << type); 644#endif 645 } 646 break; 647 case MODE_NAK: 648 case MODE_REJ: 649 LcpInfo.want_acfcomp = 0; 650 LcpInfo.his_reject |= (1 << type); 651 break; 652 } 653 break; 654 case TY_SDP: 655 LogPrintf(LogLCP, " %s\n", request); 656 switch (mode) { 657 case MODE_REQ: 658 case MODE_NAK: 659 case MODE_REJ: 660 break; 661 } 662 break; 663 default: 664 LogPrintf(LogLCP, " ???[%02x]\n", type); 665 if (mode == MODE_REQ) { 666 reqreject: 667 memcpy(rejp, cp, length); 668 rejp += length; 669 LcpInfo.my_reject |= (1 << type); 670 } 671 break; 672 } 673 /* to avoid inf. loop */ 674 if (length == 0) { 675 LogPrintf(LogLCP, "LCP size zero\n"); 676 break; 677 } 678 plen -= length; 679 cp += length; 680 } 681} 682 683void 684LcpInput(struct mbuf * bp) 685{ 686 FsmInput(&LcpFsm, bp); 687}
|