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