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