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