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