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