1 /* 2 * PPP Finite State Machine for LCP/IPCP 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: fsm.c,v 1.5 1996/01/11 17:48:44 phk Exp $ 21 * 22 * TODO: 23 * o Refer loglevel for log output 24 * o Better option log display 25 */ 26 #include "fsm.h" 27 #include "hdlc.h" 28 #include "lqr.h" 29 #include "lcpproto.h" 30 #include "lcp.h" 31 #include "ccp.h" 32 33 void FsmSendConfigReq(struct fsm *fp); 34 void FsmSendTerminateReq(struct fsm *fp); 35 void FsmInitRestartCounter(struct fsm *fp); 36 void FsmTimeout(struct fsm *fp); 37 38 char const *StateNames[] = { 39 "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 40 "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opend", 41 }; 42 43 void 44 FsmInit(fp) 45 struct fsm *fp; 46 { 47 #ifdef DEBUG 48 logprintf("FsmInit\n"); 49 #endif 50 fp->state = ST_INITIAL; 51 fp->reqid = 1; 52 fp->restart = 1; 53 fp->maxconfig = 3; 54 } 55 56 void 57 NewState(fp, new) 58 struct fsm *fp; 59 int new; 60 { 61 LogPrintf(LOG_LCP, "%s: state change %s --> %s\n", 62 fp->name, StateNames[fp->state], StateNames[new]); 63 fp->state = new; 64 if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) 65 StopTimer(&fp->FsmTimer); 66 } 67 68 void 69 FsmOutput(fp, code, id, ptr, count) 70 struct fsm *fp; 71 u_int code, id; 72 u_char *ptr; 73 int count; 74 { 75 int plen; 76 struct fsmheader lh; 77 struct mbuf *bp; 78 79 plen = sizeof(struct fsmheader) + count; 80 lh.code = code; 81 lh.id = id; 82 lh.length = htons(plen); 83 bp = mballoc(plen, MB_FSM); 84 bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 85 if (count) 86 bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 87 #ifdef DEBUG 88 DumpBp(bp); 89 #endif 90 HdlcOutput(PRI_LINK, fp->proto, bp); 91 } 92 93 void 94 FsmOpen(fp) 95 struct fsm *fp; 96 { 97 switch (fp->state) { 98 case ST_INITIAL: 99 (fp->LayerStart)(fp); 100 NewState(fp, ST_STARTING); 101 break; 102 case ST_STARTING: 103 break; 104 case ST_CLOSED: 105 if (fp->open_mode == OPEN_PASSIVE) { 106 NewState(fp, ST_STOPPED); 107 } else { 108 FsmInitRestartCounter(fp); 109 FsmSendConfigReq(fp); 110 NewState(fp, ST_REQSENT); 111 } 112 break; 113 case ST_STOPPED: /* XXX: restart option */ 114 case ST_REQSENT: 115 case ST_ACKRCVD: 116 case ST_ACKSENT: 117 case ST_OPENED: /* XXX: restart option */ 118 break; 119 case ST_CLOSING: /* XXX: restart option */ 120 case ST_STOPPING: /* XXX: restart option */ 121 NewState(fp, ST_STOPPING); 122 break; 123 } 124 } 125 126 void 127 FsmUp(fp) 128 struct fsm *fp; 129 { 130 switch (fp->state) { 131 case ST_INITIAL: 132 NewState(fp, ST_CLOSED); 133 break; 134 case ST_STARTING: 135 FsmInitRestartCounter(fp); 136 FsmSendConfigReq(fp); 137 NewState(fp, ST_REQSENT); 138 break; 139 default: 140 LogPrintf(LOG_LCP, "%s: Oops, Up at %s\n", 141 fp->name, StateNames[fp->state]); 142 break; 143 } 144 } 145 146 void 147 FsmDown(fp) 148 struct fsm *fp; 149 { 150 switch (fp->state) { 151 case ST_CLOSED: 152 case ST_CLOSING: 153 NewState(fp, ST_INITIAL); 154 break; 155 case ST_STOPPED: 156 (fp->LayerStart)(fp); 157 /* Fall into.. */ 158 case ST_STOPPING: 159 case ST_REQSENT: 160 case ST_ACKRCVD: 161 case ST_ACKSENT: 162 NewState(fp, ST_STARTING); 163 break; 164 case ST_OPENED: 165 (fp->LayerDown)(fp); 166 NewState(fp, ST_STARTING); 167 break; 168 } 169 } 170 171 void 172 FsmClose(fp) 173 struct fsm *fp; 174 { 175 switch (fp->state) { 176 case ST_STARTING: 177 NewState(fp, ST_INITIAL); 178 break; 179 case ST_STOPPED: 180 NewState(fp, ST_CLOSED); 181 break; 182 case ST_STOPPING: 183 NewState(fp, ST_CLOSING); 184 break; 185 case ST_OPENED: 186 (fp->LayerDown)(fp); 187 /* Fall down */ 188 case ST_REQSENT: 189 case ST_ACKRCVD: 190 case ST_ACKSENT: 191 FsmInitRestartCounter(fp); 192 FsmSendTerminateReq(fp); 193 NewState(fp, ST_CLOSING); 194 break; 195 } 196 } 197 198 /* 199 * Send functions 200 */ 201 void 202 FsmSendConfigReq(fp) 203 struct fsm *fp; 204 { 205 if (--fp->maxconfig > 0) { 206 (fp->SendConfigReq)(fp); 207 StartTimer(&fp->FsmTimer); /* Start restart timer */ 208 fp->restart--; /* Decrement restart counter */ 209 } else { 210 FsmClose(fp); 211 } 212 } 213 214 void 215 FsmSendTerminateReq(fp) 216 struct fsm *fp; 217 { 218 LogPrintf(LOG_LCP, "%s: SendTerminateReq.\n", fp->name); 219 FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0); 220 (fp->SendTerminateReq)(fp); 221 StartTimer(&fp->FsmTimer); /* Start restart timer */ 222 fp->restart--; /* Decrement restart counter */ 223 } 224 225 static void 226 FsmSendConfigAck(fp, lhp, option, count) 227 struct fsm *fp; 228 struct fsmheader *lhp; 229 u_char *option; 230 int count; 231 { 232 LogPrintf(LOG_LCP, "%s: SendConfigAck(%s)\n", fp->name, StateNames[fp->state]); 233 (fp->DecodeConfig)(option, count, MODE_NOP); 234 FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count); 235 } 236 237 static void 238 FsmSendConfigRej(fp, lhp, option, count) 239 struct fsm *fp; 240 struct fsmheader *lhp; 241 u_char *option; 242 int count; 243 { 244 LogPrintf(LOG_LCP, "%s: SendConfigRej(%s)\n", fp->name, StateNames[fp->state]); 245 (fp->DecodeConfig)(option, count, MODE_NOP); 246 FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count); 247 } 248 249 static void 250 FsmSendConfigNak(fp, lhp, option, count) 251 struct fsm *fp; 252 struct fsmheader *lhp; 253 u_char *option; 254 int count; 255 { 256 LogPrintf(LOG_LCP, "%s: SendConfigNak(%s)\n", 257 fp->name, StateNames[fp->state]); 258 (fp->DecodeConfig)(option, count, MODE_NOP); 259 FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count); 260 } 261 262 /* 263 * Timeout actions 264 */ 265 void 266 FsmTimeout(fp) 267 struct fsm *fp; 268 { 269 if (fp->restart) { 270 switch (fp->state) { 271 case ST_CLOSING: 272 case ST_STOPPING: 273 FsmSendTerminateReq(fp); 274 break; 275 case ST_REQSENT: 276 case ST_ACKSENT: 277 FsmSendConfigReq(fp); 278 break; 279 case ST_ACKRCVD: 280 FsmSendConfigReq(fp); 281 NewState(fp, ST_REQSENT); 282 break; 283 } 284 StartTimer(&fp->FsmTimer); 285 } else { 286 switch (fp->state) { 287 case ST_CLOSING: 288 NewState(fp, ST_CLOSED); 289 (fp->LayerFinish)(fp); 290 break; 291 case ST_STOPPING: 292 NewState(fp, ST_STOPPED); 293 (fp->LayerFinish)(fp); 294 break; 295 case ST_REQSENT: /* XXX: 3p */ 296 case ST_ACKSENT: 297 case ST_ACKRCVD: 298 NewState(fp, ST_STOPPED); 299 (fp->LayerFinish)(fp); 300 break; 301 } 302 } 303 } 304 305 void 306 FsmInitRestartCounter(fp) 307 struct fsm *fp; 308 { 309 StopTimer(&fp->FsmTimer); 310 fp->FsmTimer.state = TIMER_STOPPED; 311 fp->FsmTimer.func = FsmTimeout; 312 fp->FsmTimer.arg = (void *)fp; 313 (fp->InitRestartCounter)(fp); 314 } 315 316 /* 317 * Actions when receive packets 318 */ 319 void 320 FsmRecvConfigReq(fp, lhp, bp) /* RCR */ 321 struct fsm *fp; 322 struct fsmheader *lhp; 323 struct mbuf *bp; 324 { 325 int plen, flen; 326 int ackaction = 0; 327 328 plen = plength(bp); 329 flen = ntohs(lhp->length) - sizeof(*lhp); 330 if (plen < flen) { 331 logprintf("** plen (%d) < flen (%d)\n", plen, flen); 332 pfree(bp); 333 return; 334 } 335 336 337 /* 338 * Check and process easy case 339 */ 340 switch (fp->state) { 341 case ST_INITIAL: 342 case ST_STARTING: 343 LogPrintf(LOG_LCP, "%s: Oops, RCR in %s.\n", 344 fp->name, StateNames[fp->state]); 345 pfree(bp); 346 return; 347 case ST_CLOSED: 348 (fp->SendTerminateAck)(fp); 349 pfree(bp); 350 return; 351 case ST_CLOSING: 352 case ST_STOPPING: 353 logprintf("## state = %d\n", fp->state); 354 pfree(bp); 355 return; 356 } 357 358 (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_REQ); 359 360 if (nakp == NakBuff && rejp == RejBuff) 361 ackaction = 1; 362 363 switch (fp->state) { 364 case ST_OPENED: 365 (fp->LayerDown)(fp); 366 FsmSendConfigReq(fp); 367 break; 368 case ST_STOPPED: 369 FsmInitRestartCounter(fp); 370 FsmSendConfigReq(fp); 371 break; 372 } 373 374 if (rejp != RejBuff) 375 FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff); 376 if (nakp != NakBuff) 377 FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff); 378 if (ackaction) 379 FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff); 380 381 switch (fp->state) { 382 case ST_STOPPED: 383 case ST_OPENED: 384 if (ackaction) 385 NewState(fp, ST_ACKSENT); 386 else 387 NewState(fp, ST_REQSENT); 388 break; 389 case ST_REQSENT: 390 if (ackaction) 391 NewState(fp, ST_ACKSENT); 392 break; 393 case ST_ACKRCVD: 394 if (ackaction) { 395 NewState(fp, ST_OPENED); 396 (fp->LayerUp)(fp); 397 } 398 break; 399 case ST_ACKSENT: 400 if (!ackaction) 401 NewState(fp, ST_REQSENT); 402 break; 403 } 404 pfree(bp); 405 } 406 407 void 408 FsmRecvConfigAck(fp, lhp, bp) /* RCA */ 409 struct fsm *fp; 410 struct fsmheader *lhp; 411 struct mbuf *bp; 412 { 413 switch (fp->state) { 414 case ST_CLOSED: 415 case ST_STOPPED: 416 (fp->SendTerminateAck)(fp); 417 break; 418 case ST_CLOSING: 419 case ST_STOPPING: 420 break; 421 case ST_REQSENT: 422 FsmInitRestartCounter(fp); 423 NewState(fp, ST_ACKRCVD); 424 break; 425 case ST_ACKRCVD: 426 FsmSendConfigReq(fp); 427 NewState(fp, ST_REQSENT); 428 break; 429 case ST_ACKSENT: 430 FsmInitRestartCounter(fp); 431 NewState(fp, ST_OPENED); 432 (fp->LayerUp)(fp); 433 break; 434 case ST_OPENED: 435 (fp->LayerDown)(fp); 436 FsmSendConfigReq(fp); 437 NewState(fp, ST_REQSENT); 438 break; 439 } 440 pfree(bp); 441 } 442 443 void 444 FsmRecvConfigNak(fp, lhp, bp) /* RCN */ 445 struct fsm *fp; 446 struct fsmheader *lhp; 447 struct mbuf *bp; 448 { 449 int plen, flen; 450 451 plen = plength(bp); 452 flen = ntohs(lhp->length) - sizeof(*lhp); 453 if (plen < flen) { 454 pfree(bp); 455 return; 456 } 457 458 /* 459 * Check and process easy case 460 */ 461 switch (fp->state) { 462 case ST_INITIAL: 463 case ST_STARTING: 464 LogPrintf(LOG_LCP, "%s: Oops, RCN in %s.\n", 465 fp->name, StateNames[fp->state]); 466 pfree(bp); 467 return; 468 case ST_CLOSED: 469 case ST_STOPPED: 470 (fp->SendTerminateAck)(fp); 471 pfree(bp); 472 return; 473 case ST_CLOSING: 474 case ST_STOPPING: 475 pfree(bp); 476 return; 477 } 478 479 (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_NAK); 480 481 switch (fp->state) { 482 case ST_REQSENT: 483 case ST_ACKSENT: 484 FsmInitRestartCounter(fp); 485 FsmSendConfigReq(fp); 486 break; 487 case ST_OPENED: 488 (fp->LayerDown)(fp); 489 /* Fall down */ 490 case ST_ACKRCVD: 491 FsmSendConfigReq(fp); 492 NewState(fp, ST_REQSENT); 493 break; 494 } 495 496 pfree(bp); 497 } 498 499 void 500 FsmRecvTermReq(fp, lhp, bp) /* RTR */ 501 struct fsm *fp; 502 struct fsmheader *lhp; 503 struct mbuf *bp; 504 { 505 switch (fp->state) { 506 case ST_INITIAL: 507 case ST_STARTING: 508 LogPrintf(LOG_LCP, "%s: Oops, RTR in %s\n", fp->name, 509 StateNames[fp->state]); 510 break; 511 case ST_CLOSED: 512 case ST_STOPPED: 513 case ST_CLOSING: 514 case ST_STOPPING: 515 case ST_REQSENT: 516 (fp->SendTerminateAck)(fp); 517 break; 518 case ST_ACKRCVD: 519 case ST_ACKSENT: 520 (fp->SendTerminateAck)(fp); 521 NewState(fp, ST_REQSENT); 522 break; 523 case ST_OPENED: 524 (fp->LayerDown)(fp); 525 /* Zero Restart counter */ 526 (fp->SendTerminateAck)(fp); 527 NewState(fp, ST_STOPPING); 528 break; 529 } 530 pfree(bp); 531 } 532 533 void 534 FsmRecvTermAck(fp, lhp, bp) /* RTA */ 535 struct fsm *fp; 536 struct fsmheader *lhp; 537 struct mbuf *bp; 538 { 539 switch (fp->state) { 540 case ST_CLOSING: 541 NewState(fp, ST_CLOSED); 542 (fp->LayerFinish)(fp); 543 break; 544 case ST_STOPPING: 545 NewState(fp, ST_STOPPED); 546 (fp->LayerFinish)(fp); 547 break; 548 case ST_ACKRCVD: 549 NewState(fp, ST_REQSENT); 550 break; 551 case ST_OPENED: 552 (fp->LayerDown)(fp); 553 FsmSendConfigReq(fp); 554 NewState(fp, ST_REQSENT); 555 break; 556 } 557 pfree(bp); 558 } 559 560 void 561 FsmRecvConfigRej(fp, lhp, bp) /* RCJ */ 562 struct fsm *fp; 563 struct fsmheader *lhp; 564 struct mbuf *bp; 565 { 566 int plen, flen; 567 568 plen = plength(bp); 569 flen = ntohs(lhp->length) - sizeof(*lhp); 570 if (plen < flen) { 571 pfree(bp); 572 return; 573 } 574 LogPrintf(LOG_LCP, "%s: RecvConfigRej.\n", fp->name); 575 576 /* 577 * Check and process easy case 578 */ 579 switch (fp->state) { 580 case ST_INITIAL: 581 case ST_STARTING: 582 LogPrintf(LOG_LCP, "%s: Oops, RCJ in %s.\n", 583 fp->name, StateNames[fp->state]); 584 pfree(bp); 585 return; 586 case ST_CLOSED: 587 case ST_STOPPED: 588 (fp->SendTerminateAck)(fp); 589 pfree(bp); 590 return; 591 case ST_CLOSING: 592 case ST_STOPPING: 593 pfree(bp); 594 return; 595 } 596 597 (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_REJ); 598 599 switch (fp->state) { 600 case ST_REQSENT: 601 case ST_ACKSENT: 602 FsmInitRestartCounter(fp); 603 FsmSendConfigReq(fp); 604 break; 605 case ST_OPENED: 606 (fp->LayerDown)(fp); 607 /* Fall down */ 608 case ST_ACKRCVD: 609 FsmSendConfigReq(fp); 610 NewState(fp, ST_REQSENT); 611 break; 612 } 613 pfree(bp); 614 } 615 616 void 617 FsmRecvCodeRej(fp, lhp, bp) 618 struct fsm *fp; 619 struct fsmheader *lhp; 620 struct mbuf *bp; 621 { 622 LogPrintf(LOG_LCP, "%s: RecvCodeRej\n", fp->name); 623 pfree(bp); 624 } 625 626 void 627 FsmRecvProtoRej(fp, lhp, bp) 628 struct fsm *fp; 629 struct fsmheader *lhp; 630 struct mbuf *bp; 631 { 632 u_short *sp, proto; 633 634 sp = (u_short *)MBUF_CTOP(bp); 635 proto = ntohs(*sp); 636 LogPrintf(LOG_LCP, "-- Protocol (%04x) was rejected.\n", proto); 637 638 switch (proto) { 639 case PROTO_LQR: 640 StopLqr(LQM_LQR); 641 break; 642 case PROTO_CCP: 643 fp = &CcpFsm; 644 (fp->LayerFinish)(fp); 645 switch (fp->state) { 646 case ST_CLOSED: 647 case ST_CLOSING: 648 NewState(fp, ST_CLOSED); 649 default: 650 NewState(fp, ST_STOPPED); 651 break; 652 } 653 break; 654 } 655 pfree(bp); 656 } 657 658 void 659 FsmRecvEchoReq(fp, lhp, bp) 660 struct fsm *fp; 661 struct fsmheader *lhp; 662 struct mbuf *bp; 663 { 664 u_char *cp; 665 u_long *lp, magic; 666 667 cp = MBUF_CTOP(bp); 668 lp = (u_long *)cp; 669 magic = ntohl(*lp); 670 if (magic != LcpInfo.his_magic) { 671 logprintf("RecvEchoReq: his magic is bad!!\n"); 672 /* XXX: We should send terminate request */ 673 } 674 675 if (fp->state == ST_OPENED) { 676 *lp = htonl(LcpInfo.want_magic); /* Insert local magic number */ 677 LogPrintf(LOG_LCP, "%s: SendEchoRep(%s)\n", fp->name, StateNames[fp->state]); 678 FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp)); 679 } 680 pfree(bp); 681 } 682 683 void 684 FsmRecvEchoRep(fp, lhp, bp) 685 struct fsm *fp; 686 struct fsmheader *lhp; 687 struct mbuf *bp; 688 { 689 u_long *lp, magic; 690 691 lp = (u_long *)MBUF_CTOP(bp); 692 magic = ntohl(*lp); 693 /* 694 * Tolerate echo replies with either magic number 695 */ 696 if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) { 697 logprintf("RecvEchoRep: his magic is wrong! expect: %x got: %x\n", 698 LcpInfo.his_magic, magic); 699 /* 700 * XXX: We should send terminate request. But poor implementation 701 * may die as a result. 702 */ 703 } 704 RecvEchoLqr(bp); 705 pfree(bp); 706 } 707 708 void 709 FsmRecvDiscReq(fp, lhp, bp) 710 struct fsm *fp; 711 struct fsmheader *lhp; 712 struct mbuf *bp; 713 { 714 LogPrintf(LOG_LCP, "%s: RecvDiscReq\n", fp->name); 715 pfree(bp); 716 } 717 718 void 719 FsmRecvIdent(fp, lhp, bp) 720 struct fsm *fp; 721 struct fsmheader *lhp; 722 struct mbuf *bp; 723 { 724 LogPrintf(LOG_LCP, "%s: RecvIdent\n", fp->name); 725 pfree(bp); 726 } 727 728 void 729 FsmRecvTimeRemain(fp, lhp, bp) 730 struct fsm *fp; 731 struct fsmheader *lhp; 732 struct mbuf *bp; 733 { 734 LogPrintf(LOG_LCP, "%s: RecvTimeRemain\n", fp->name); 735 pfree(bp); 736 } 737 738 void 739 FsmRecvResetReq(fp, lhp, bp) 740 struct fsm *fp; 741 struct fsmheader *lhp; 742 struct mbuf *bp; 743 { 744 LogPrintf(LOG_LCP, "%s: RecvResetReq\n", fp->name); 745 CcpRecvResetReq(fp); 746 LogPrintf(LOG_LCP, "%s: SendResetAck\n", fp->name); 747 FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0); 748 pfree(bp); 749 } 750 751 void 752 FsmRecvResetAck(fp, lhp, bp) 753 struct fsm *fp; 754 struct fsmheader *lhp; 755 struct mbuf *bp; 756 { 757 LogPrintf(LOG_LCP, "%s: RecvResetAck\n", fp->name); 758 fp->reqid++; 759 pfree(bp); 760 } 761 762 struct fsmcodedesc FsmCodes[] = { 763 { FsmRecvConfigReq, "Configure Request", }, 764 { FsmRecvConfigAck, "Configure Ack", }, 765 { FsmRecvConfigNak, "Configure Nak", }, 766 { FsmRecvConfigRej, "Configure Reject", }, 767 { FsmRecvTermReq, "Terminate Request", }, 768 { FsmRecvTermAck, "Terminate Ack", }, 769 { FsmRecvCodeRej, "Code Reject", }, 770 { FsmRecvProtoRej, "Protocol Reject", }, 771 { FsmRecvEchoReq, "Echo Request", }, 772 { FsmRecvEchoRep, "Echo Reply", }, 773 { FsmRecvDiscReq, "Discard Request", }, 774 { FsmRecvIdent, "Ident", }, 775 { FsmRecvTimeRemain, "Time Remain", }, 776 { FsmRecvResetReq, "Reset Request", }, 777 { FsmRecvResetAck, "Reset Ack", }, 778 }; 779 780 void 781 FsmInput(fp, bp) 782 struct fsm *fp; 783 struct mbuf *bp; 784 { 785 int len; 786 struct fsmheader *lhp; 787 struct fsmcodedesc *codep; 788 789 len = plength(bp); 790 if (len < sizeof(struct fsmheader)) { 791 pfree(bp); 792 return; 793 } 794 lhp = (struct fsmheader *)MBUF_CTOP(bp); 795 if (lhp->code == 0 || lhp->code > fp->max_code) { 796 pfree(bp); /* XXX: Should send code reject */ 797 return; 798 } 799 800 bp->offset += sizeof(struct fsmheader); 801 bp->cnt -= sizeof(struct fsmheader); 802 803 codep = FsmCodes + lhp->code - 1; 804 LogPrintf(LOG_LCP, "%s: Received %s (%d) state = %s (%d)\n", 805 fp->name, codep->name, lhp->id, StateNames[fp->state], fp->state); 806 #ifdef DEBUG 807 LogMemory(); 808 #endif 809 (codep->action)(fp, lhp, bp); 810 #ifdef DEBUG 811 LogMemory(); 812 #endif 813 } 814