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