fsm.c revision 37060
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.30 1998/06/16 19:40:36 brian Exp $ 21 * 22 * TODO: 23 */ 24 25#include <sys/types.h> 26#include <netinet/in.h> 27#include <netinet/in_systm.h> 28#include <netinet/ip.h> 29#include <sys/un.h> 30 31#include <string.h> 32#include <termios.h> 33 34#include "mbuf.h" 35#include "log.h" 36#include "defs.h" 37#include "timer.h" 38#include "fsm.h" 39#include "iplist.h" 40#include "lqr.h" 41#include "hdlc.h" 42#include "throughput.h" 43#include "slcompress.h" 44#include "ipcp.h" 45#include "filter.h" 46#include "descriptor.h" 47#include "lcp.h" 48#include "ccp.h" 49#include "link.h" 50#include "mp.h" 51#include "bundle.h" 52#include "async.h" 53#include "physical.h" 54#include "lcpproto.h" 55 56static void FsmSendConfigReq(struct fsm *); 57static void FsmSendTerminateReq(struct fsm *); 58static void FsmInitRestartCounter(struct fsm *); 59 60typedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *); 61static recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak, 62 FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck, 63 FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq, 64 FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent, 65 FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck; 66 67static const struct fsmcodedesc { 68 recvfn *recv; 69 unsigned check_reqid : 1; 70 unsigned inc_reqid : 1; 71 const char *name; 72} FsmCodes[] = { 73 { FsmRecvConfigReq, 0, 0, "ConfigReq" }, 74 { FsmRecvConfigAck, 1, 1, "ConfigAck" }, 75 { FsmRecvConfigNak, 1, 1, "ConfigNak" }, 76 { FsmRecvConfigRej, 1, 1, "ConfigRej" }, 77 { FsmRecvTermReq, 0, 0, "TerminateReq" }, 78 { FsmRecvTermAck, 1, 1, "TerminateAck" }, 79 { FsmRecvCodeRej, 0, 0, "CodeRej" }, 80 { FsmRecvProtoRej, 0, 0, "ProtocolRej" }, 81 { FsmRecvEchoReq, 0, 0, "EchoRequest" }, 82 { FsmRecvEchoRep, 0, 0, "EchoReply" }, 83 { FsmRecvDiscReq, 0, 0, "DiscardReq" }, 84 { FsmRecvIdent, 0, 0, "Ident" }, 85 { FsmRecvTimeRemain,0, 0, "TimeRemain" }, 86 { FsmRecvResetReq, 0, 0, "ResetReqt" }, 87 { FsmRecvResetAck, 0, 1, "ResetAck" } 88}; 89 90static const char * 91Code2Nam(u_int code) 92{ 93 if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0]) 94 return "Unknown"; 95 return FsmCodes[code-1].name; 96} 97 98const char * 99State2Nam(u_int state) 100{ 101 static const char *StateNames[] = { 102 "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 103 "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 104 }; 105 106 if (state >= sizeof StateNames / sizeof StateNames[0]) 107 return "unknown"; 108 return StateNames[state]; 109} 110 111static void 112StoppedTimeout(void *v) 113{ 114 struct fsm *fp = (struct fsm *)v; 115 116 log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name); 117 if (fp->OpenTimer.state == TIMER_RUNNING) { 118 log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n", 119 fp->link->name, fp->name); 120 timer_Stop(&fp->OpenTimer); 121 } 122 if (fp->state == ST_STOPPED) 123 fsm2initial(fp); 124} 125 126void 127fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode, 128 int maxcode, int maxcfg, int LogLevel, struct bundle *bundle, 129 struct link *l, const struct fsm_parent *parent, 130 struct fsm_callbacks *fn, const char *timer_names[3]) 131{ 132 fp->name = name; 133 fp->proto = proto; 134 fp->min_code = mincode; 135 fp->max_code = maxcode; 136 fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL; 137 fp->reqid = 1; 138 fp->restart = 1; 139 fp->maxconfig = maxcfg; 140 memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer); 141 memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer); 142 memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer); 143 fp->LogLevel = LogLevel; 144 fp->link = l; 145 fp->bundle = bundle; 146 fp->parent = parent; 147 fp->fn = fn; 148 fp->FsmTimer.name = timer_names[0]; 149 fp->OpenTimer.name = timer_names[1]; 150 fp->StoppedTimer.name = timer_names[2]; 151} 152 153static void 154NewState(struct fsm * fp, int new) 155{ 156 log_Printf(fp->LogLevel, "%s: State change %s --> %s\n", 157 fp->link->name, State2Nam(fp->state), State2Nam(new)); 158 if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 159 timer_Stop(&fp->StoppedTimer); 160 fp->state = new; 161 if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 162 timer_Stop(&fp->FsmTimer); 163 if (new == ST_STOPPED && fp->StoppedTimer.load) { 164 timer_Stop(&fp->StoppedTimer); 165 fp->StoppedTimer.func = StoppedTimeout; 166 fp->StoppedTimer.arg = (void *) fp; 167 timer_Start(&fp->StoppedTimer); 168 } 169 } 170} 171 172void 173fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count) 174{ 175 int plen; 176 struct fsmheader lh; 177 struct mbuf *bp; 178 179 if (log_IsKept(fp->LogLevel)) { 180 log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n", 181 fp->link->name, Code2Nam(code), id, State2Nam(fp->state)); 182 switch (code) { 183 case CODE_CONFIGREQ: 184 case CODE_CONFIGACK: 185 case CODE_CONFIGREJ: 186 case CODE_CONFIGNAK: 187 (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL); 188 if (count < sizeof(struct fsmconfig)) 189 log_Printf(fp->LogLevel, " [EMPTY]\n"); 190 break; 191 } 192 } 193 194 plen = sizeof(struct fsmheader) + count; 195 lh.code = code; 196 lh.id = id; 197 lh.length = htons(plen); 198 bp = mbuf_Alloc(plen, MB_FSM); 199 memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 200 if (count) 201 memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 202 log_DumpBp(LogDEBUG, "fsm_Output", bp); 203 hdlc_Output(fp->link, PRI_LINK, fp->proto, bp); 204} 205 206static void 207FsmOpenNow(void *v) 208{ 209 struct fsm *fp = (struct fsm *)v; 210 211 timer_Stop(&fp->OpenTimer); 212 if (fp->state <= ST_STOPPED) { 213 FsmInitRestartCounter(fp); 214 FsmSendConfigReq(fp); 215 NewState(fp, ST_REQSENT); 216 } 217} 218 219void 220fsm_Open(struct fsm * fp) 221{ 222 switch (fp->state) { 223 case ST_INITIAL: 224 NewState(fp, ST_STARTING); 225 (*fp->fn->LayerStart)(fp); 226 (*fp->parent->LayerStart)(fp->parent->object, fp); 227 break; 228 case ST_CLOSED: 229 if (fp->open_mode == OPEN_PASSIVE) { 230 NewState(fp, ST_STOPPED); 231 } else if (fp->open_mode > 0) { 232 if (fp->open_mode > 1) 233 log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n", 234 fp->link->name, fp->open_mode); 235 NewState(fp, ST_STOPPED); 236 timer_Stop(&fp->OpenTimer); 237 fp->OpenTimer.load = fp->open_mode * SECTICKS; 238 fp->OpenTimer.func = FsmOpenNow; 239 fp->OpenTimer.arg = (void *)fp; 240 timer_Start(&fp->OpenTimer); 241 } else 242 FsmOpenNow(fp); 243 break; 244 case ST_STOPPED: /* XXX: restart option */ 245 case ST_REQSENT: 246 case ST_ACKRCVD: 247 case ST_ACKSENT: 248 case ST_OPENED: /* XXX: restart option */ 249 break; 250 case ST_CLOSING: /* XXX: restart option */ 251 case ST_STOPPING: /* XXX: restart option */ 252 NewState(fp, ST_STOPPING); 253 break; 254 } 255} 256 257void 258fsm_Up(struct fsm * fp) 259{ 260 switch (fp->state) { 261 case ST_INITIAL: 262 log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n", 263 fp->link->name); 264 NewState(fp, ST_CLOSED); 265 break; 266 case ST_STARTING: 267 FsmInitRestartCounter(fp); 268 FsmSendConfigReq(fp); 269 NewState(fp, ST_REQSENT); 270 break; 271 default: 272 log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n", 273 fp->link->name, State2Nam(fp->state)); 274 break; 275 } 276} 277 278void 279fsm_Down(struct fsm *fp) 280{ 281 switch (fp->state) { 282 case ST_CLOSED: 283 NewState(fp, ST_INITIAL); 284 break; 285 case ST_CLOSING: 286 (*fp->fn->LayerFinish)(fp); 287 NewState(fp, ST_INITIAL); 288 (*fp->parent->LayerFinish)(fp->parent->object, fp); 289 break; 290 case ST_STOPPED: 291 NewState(fp, ST_STARTING); 292 (*fp->fn->LayerStart)(fp); 293 (*fp->parent->LayerStart)(fp->parent->object, fp); 294 break; 295 case ST_STOPPING: 296 case ST_REQSENT: 297 case ST_ACKRCVD: 298 case ST_ACKSENT: 299 NewState(fp, ST_STARTING); 300 break; 301 case ST_OPENED: 302 (*fp->fn->LayerDown)(fp); 303 NewState(fp, ST_STARTING); 304 (*fp->parent->LayerDown)(fp->parent->object, fp); 305 break; 306 } 307} 308 309void 310fsm_Close(struct fsm *fp) 311{ 312 switch (fp->state) { 313 case ST_STARTING: 314 (*fp->fn->LayerFinish)(fp); 315 NewState(fp, ST_INITIAL); 316 (*fp->parent->LayerFinish)(fp->parent->object, fp); 317 break; 318 case ST_STOPPED: 319 NewState(fp, ST_CLOSED); 320 break; 321 case ST_STOPPING: 322 NewState(fp, ST_CLOSING); 323 break; 324 case ST_OPENED: 325 (*fp->fn->LayerDown)(fp); 326 FsmInitRestartCounter(fp); 327 FsmSendTerminateReq(fp); 328 NewState(fp, ST_CLOSING); 329 (*fp->parent->LayerDown)(fp->parent->object, fp); 330 break; 331 case ST_REQSENT: 332 case ST_ACKRCVD: 333 case ST_ACKSENT: 334 FsmInitRestartCounter(fp); 335 FsmSendTerminateReq(fp); 336 NewState(fp, ST_CLOSING); 337 break; 338 } 339} 340 341/* 342 * Send functions 343 */ 344static void 345FsmSendConfigReq(struct fsm * fp) 346{ 347 if (--fp->maxconfig > 0) { 348 (*fp->fn->SendConfigReq)(fp); 349 timer_Start(&fp->FsmTimer); /* Start restart timer */ 350 fp->restart--; /* Decrement restart counter */ 351 } else { 352 fsm_Close(fp); 353 } 354} 355 356static void 357FsmSendTerminateReq(struct fsm *fp) 358{ 359 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 360 (*fp->fn->SentTerminateReq)(fp); 361 timer_Start(&fp->FsmTimer); /* Start restart timer */ 362 fp->restart--; /* Decrement restart counter */ 363} 364 365/* 366 * Timeout actions 367 */ 368static void 369FsmTimeout(void *v) 370{ 371 struct fsm *fp = (struct fsm *)v; 372 373 if (fp->restart) { 374 switch (fp->state) { 375 case ST_CLOSING: 376 case ST_STOPPING: 377 FsmSendTerminateReq(fp); 378 break; 379 case ST_REQSENT: 380 case ST_ACKSENT: 381 FsmSendConfigReq(fp); 382 break; 383 case ST_ACKRCVD: 384 FsmSendConfigReq(fp); 385 NewState(fp, ST_REQSENT); 386 break; 387 } 388 timer_Start(&fp->FsmTimer); 389 } else { 390 switch (fp->state) { 391 case ST_CLOSING: 392 (*fp->fn->LayerFinish)(fp); 393 NewState(fp, ST_CLOSED); 394 (*fp->parent->LayerFinish)(fp->parent->object, fp); 395 break; 396 case ST_STOPPING: 397 (*fp->fn->LayerFinish)(fp); 398 NewState(fp, ST_STOPPED); 399 (*fp->parent->LayerFinish)(fp->parent->object, fp); 400 break; 401 case ST_REQSENT: /* XXX: 3p */ 402 case ST_ACKSENT: 403 case ST_ACKRCVD: 404 (*fp->fn->LayerFinish)(fp); 405 NewState(fp, ST_STOPPED); 406 (*fp->parent->LayerFinish)(fp->parent->object, fp); 407 break; 408 } 409 } 410} 411 412static void 413FsmInitRestartCounter(struct fsm * fp) 414{ 415 timer_Stop(&fp->FsmTimer); 416 fp->FsmTimer.func = FsmTimeout; 417 fp->FsmTimer.arg = (void *) fp; 418 (*fp->fn->InitRestartCounter)(fp); 419} 420 421/* 422 * Actions when receive packets 423 */ 424static void 425FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 426/* RCR */ 427{ 428 struct fsm_decode dec; 429 int plen, flen; 430 int ackaction = 0; 431 432 plen = mbuf_Length(bp); 433 flen = ntohs(lhp->length) - sizeof *lhp; 434 if (plen < flen) { 435 log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 436 fp->link->name, plen, flen); 437 mbuf_Free(bp); 438 return; 439 } 440 441 /* 442 * Check and process easy case 443 */ 444 switch (fp->state) { 445 case ST_INITIAL: 446 case ST_STARTING: 447 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 448 fp->link->name, State2Nam(fp->state)); 449 mbuf_Free(bp); 450 return; 451 case ST_CLOSED: 452 (*fp->fn->SendTerminateAck)(fp, lhp->id); 453 mbuf_Free(bp); 454 return; 455 case ST_CLOSING: 456 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 457 fp->link->name, State2Nam(fp->state)); 458 case ST_STOPPING: 459 mbuf_Free(bp); 460 return; 461 } 462 463 dec.ackend = dec.ack; 464 dec.nakend = dec.nak; 465 dec.rejend = dec.rej; 466 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 467 if (flen < sizeof(struct fsmconfig)) 468 log_Printf(fp->LogLevel, " [EMPTY]\n"); 469 470 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 471 ackaction = 1; 472 473 switch (fp->state) { 474 case ST_OPENED: 475 (*fp->fn->LayerDown)(fp); 476 FsmSendConfigReq(fp); 477 (*fp->parent->LayerDown)(fp->parent->object, fp); 478 break; 479 case ST_STOPPED: 480 FsmInitRestartCounter(fp); 481 FsmSendConfigReq(fp); 482 break; 483 } 484 485 if (dec.rejend != dec.rej) 486 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 487 if (dec.nakend != dec.nak) 488 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 489 if (ackaction) 490 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 491 492 switch (fp->state) { 493 case ST_OPENED: 494 case ST_STOPPED: 495 if (ackaction) 496 NewState(fp, ST_ACKSENT); 497 else 498 NewState(fp, ST_REQSENT); 499 break; 500 case ST_REQSENT: 501 if (ackaction) 502 NewState(fp, ST_ACKSENT); 503 break; 504 case ST_ACKRCVD: 505 if (ackaction) { 506 NewState(fp, ST_OPENED); 507 if ((*fp->fn->LayerUp)(fp)) 508 (*fp->parent->LayerUp)(fp->parent->object, fp); 509 else { 510 (*fp->fn->LayerDown)(fp); 511 FsmInitRestartCounter(fp); 512 FsmSendTerminateReq(fp); 513 NewState(fp, ST_CLOSING); 514 } 515 } 516 break; 517 case ST_ACKSENT: 518 if (!ackaction) 519 NewState(fp, ST_REQSENT); 520 break; 521 } 522 mbuf_Free(bp); 523} 524 525static void 526FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 527/* RCA */ 528{ 529 switch (fp->state) { 530 case ST_CLOSED: 531 case ST_STOPPED: 532 (*fp->fn->SendTerminateAck)(fp, lhp->id); 533 break; 534 case ST_CLOSING: 535 case ST_STOPPING: 536 break; 537 case ST_REQSENT: 538 FsmInitRestartCounter(fp); 539 NewState(fp, ST_ACKRCVD); 540 break; 541 case ST_ACKRCVD: 542 FsmSendConfigReq(fp); 543 NewState(fp, ST_REQSENT); 544 break; 545 case ST_ACKSENT: 546 FsmInitRestartCounter(fp); 547 NewState(fp, ST_OPENED); 548 if ((*fp->fn->LayerUp)(fp)) 549 (*fp->parent->LayerUp)(fp->parent->object, fp); 550 else { 551 (*fp->fn->LayerDown)(fp); 552 FsmInitRestartCounter(fp); 553 FsmSendTerminateReq(fp); 554 NewState(fp, ST_CLOSING); 555 } 556 break; 557 case ST_OPENED: 558 (*fp->fn->LayerDown)(fp); 559 FsmSendConfigReq(fp); 560 NewState(fp, ST_REQSENT); 561 (*fp->parent->LayerDown)(fp->parent->object, fp); 562 break; 563 } 564 mbuf_Free(bp); 565} 566 567static void 568FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 569/* RCN */ 570{ 571 struct fsm_decode dec; 572 int plen, flen; 573 574 plen = mbuf_Length(bp); 575 flen = ntohs(lhp->length) - sizeof *lhp; 576 if (plen < flen) { 577 mbuf_Free(bp); 578 return; 579 } 580 581 /* 582 * Check and process easy case 583 */ 584 switch (fp->state) { 585 case ST_INITIAL: 586 case ST_STARTING: 587 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 588 fp->link->name, State2Nam(fp->state)); 589 mbuf_Free(bp); 590 return; 591 case ST_CLOSED: 592 case ST_STOPPED: 593 (*fp->fn->SendTerminateAck)(fp, lhp->id); 594 mbuf_Free(bp); 595 return; 596 case ST_CLOSING: 597 case ST_STOPPING: 598 mbuf_Free(bp); 599 return; 600 } 601 602 dec.ackend = dec.ack; 603 dec.nakend = dec.nak; 604 dec.rejend = dec.rej; 605 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 606 if (flen < sizeof(struct fsmconfig)) 607 log_Printf(fp->LogLevel, " [EMPTY]\n"); 608 609 switch (fp->state) { 610 case ST_REQSENT: 611 case ST_ACKSENT: 612 FsmInitRestartCounter(fp); 613 FsmSendConfigReq(fp); 614 break; 615 case ST_OPENED: 616 (*fp->fn->LayerDown)(fp); 617 FsmSendConfigReq(fp); 618 NewState(fp, ST_REQSENT); 619 (*fp->parent->LayerDown)(fp->parent->object, fp); 620 break; 621 case ST_ACKRCVD: 622 FsmSendConfigReq(fp); 623 NewState(fp, ST_REQSENT); 624 break; 625 } 626 627 mbuf_Free(bp); 628} 629 630static void 631FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 632/* RTR */ 633{ 634 switch (fp->state) { 635 case ST_INITIAL: 636 case ST_STARTING: 637 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 638 fp->link->name, State2Nam(fp->state)); 639 break; 640 case ST_CLOSED: 641 case ST_STOPPED: 642 case ST_CLOSING: 643 case ST_STOPPING: 644 case ST_REQSENT: 645 (*fp->fn->SendTerminateAck)(fp, lhp->id); 646 break; 647 case ST_ACKRCVD: 648 case ST_ACKSENT: 649 (*fp->fn->SendTerminateAck)(fp, lhp->id); 650 NewState(fp, ST_REQSENT); 651 break; 652 case ST_OPENED: 653 (*fp->fn->LayerDown)(fp); 654 (*fp->fn->SendTerminateAck)(fp, lhp->id); 655 timer_Start(&fp->FsmTimer); /* Start restart timer */ 656 fp->restart = 0; 657 NewState(fp, ST_STOPPING); 658 (*fp->parent->LayerDown)(fp->parent->object, fp); 659 break; 660 } 661 mbuf_Free(bp); 662} 663 664static void 665FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 666/* RTA */ 667{ 668 switch (fp->state) { 669 case ST_CLOSING: 670 (*fp->fn->LayerFinish)(fp); 671 NewState(fp, ST_CLOSED); 672 (*fp->parent->LayerFinish)(fp->parent->object, fp); 673 break; 674 case ST_STOPPING: 675 (*fp->fn->LayerFinish)(fp); 676 NewState(fp, ST_STOPPED); 677 (*fp->parent->LayerFinish)(fp->parent->object, fp); 678 break; 679 case ST_ACKRCVD: 680 NewState(fp, ST_REQSENT); 681 break; 682 case ST_OPENED: 683 (*fp->fn->LayerDown)(fp); 684 FsmSendConfigReq(fp); 685 NewState(fp, ST_REQSENT); 686 (*fp->parent->LayerDown)(fp->parent->object, fp); 687 break; 688 } 689 mbuf_Free(bp); 690} 691 692static void 693FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 694/* RCJ */ 695{ 696 struct fsm_decode dec; 697 int plen, flen; 698 699 plen = mbuf_Length(bp); 700 flen = ntohs(lhp->length) - sizeof *lhp; 701 if (plen < flen) { 702 mbuf_Free(bp); 703 return; 704 } 705 706 /* 707 * Check and process easy case 708 */ 709 switch (fp->state) { 710 case ST_INITIAL: 711 case ST_STARTING: 712 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 713 fp->link->name, State2Nam(fp->state)); 714 mbuf_Free(bp); 715 return; 716 case ST_CLOSED: 717 case ST_STOPPED: 718 (*fp->fn->SendTerminateAck)(fp, lhp->id); 719 mbuf_Free(bp); 720 return; 721 case ST_CLOSING: 722 case ST_STOPPING: 723 mbuf_Free(bp); 724 return; 725 } 726 727 dec.ackend = dec.ack; 728 dec.nakend = dec.nak; 729 dec.rejend = dec.rej; 730 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 731 if (flen < sizeof(struct fsmconfig)) 732 log_Printf(fp->LogLevel, " [EMPTY]\n"); 733 734 switch (fp->state) { 735 case ST_REQSENT: 736 case ST_ACKSENT: 737 FsmInitRestartCounter(fp); 738 FsmSendConfigReq(fp); 739 break; 740 case ST_OPENED: 741 (*fp->fn->LayerDown)(fp); 742 FsmSendConfigReq(fp); 743 NewState(fp, ST_REQSENT); 744 (*fp->parent->LayerDown)(fp->parent->object, fp); 745 break; 746 case ST_ACKRCVD: 747 FsmSendConfigReq(fp); 748 NewState(fp, ST_REQSENT); 749 break; 750 } 751 mbuf_Free(bp); 752} 753 754static void 755FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 756{ 757 mbuf_Free(bp); 758} 759 760static void 761FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 762{ 763 struct physical *p = link2physical(fp->link); 764 u_short *sp, proto; 765 766 sp = (u_short *) MBUF_CTOP(bp); 767 proto = ntohs(*sp); 768 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 769 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 770 771 switch (proto) { 772 case PROTO_LQR: 773 if (p) 774 lqr_Stop(p, LQM_LQR); 775 else 776 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 777 fp->link->name); 778 break; 779 case PROTO_CCP: 780 if (fp->proto == PROTO_LCP) { 781 fp = &fp->link->ccp.fsm; 782 (*fp->fn->LayerFinish)(fp); 783 switch (fp->state) { 784 case ST_CLOSED: 785 case ST_CLOSING: 786 NewState(fp, ST_CLOSED); 787 default: 788 NewState(fp, ST_STOPPED); 789 break; 790 } 791 (*fp->parent->LayerFinish)(fp->parent->object, fp); 792 } 793 break; 794 case PROTO_MP: 795 if (fp->proto == PROTO_LCP) { 796 struct lcp *lcp = fsm2lcp(fp); 797 798 if (lcp->want_mrru && lcp->his_mrru) { 799 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 800 fp->link->name); 801 fsm_Close(fp); 802 } 803 } 804 break; 805 } 806 mbuf_Free(bp); 807} 808 809static void 810FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 811{ 812 struct lcp *lcp = fsm2lcp(fp); 813 u_char *cp; 814 u_int32_t magic; 815 816 if (lcp) { 817 cp = MBUF_CTOP(bp); 818 magic = ntohl(*(u_int32_t *)cp); 819 if (magic != lcp->his_magic) { 820 log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n", 821 fp->link->name); 822 /* XXX: We should send terminate request */ 823 } 824 if (fp->state == ST_OPENED) { 825 *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */ 826 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp)); 827 } 828 } 829 mbuf_Free(bp); 830} 831 832static void 833FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 834{ 835 struct lcp *lcp = fsm2lcp(fp); 836 u_int32_t magic; 837 838 if (lcp) { 839 magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp)); 840 /* Tolerate echo replies with either magic number */ 841 if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 842 log_Printf(LogWARN, 843 "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 844 fp->link->name, lcp->his_magic, magic); 845 /* 846 * XXX: We should send terminate request. But poor implementations may 847 * die as a result. 848 */ 849 } 850 lqr_RecvEcho(fp, bp); 851 } 852 mbuf_Free(bp); 853} 854 855static void 856FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 857{ 858 mbuf_Free(bp); 859} 860 861static void 862FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 863{ 864 mbuf_Free(bp); 865} 866 867static void 868FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 869{ 870 mbuf_Free(bp); 871} 872 873static void 874FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 875{ 876 (*fp->fn->RecvResetReq)(fp); 877 /* 878 * All sendable compressed packets are queued in the PRI_NORMAL modem 879 * output queue.... dump 'em to the priority queue so that they arrive 880 * at the peer before our ResetAck. 881 */ 882 link_SequenceQueue(fp->link); 883 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0); 884 mbuf_Free(bp); 885} 886 887static void 888FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 889{ 890 (*fp->fn->RecvResetAck)(fp, lhp->id); 891 mbuf_Free(bp); 892} 893 894void 895fsm_Input(struct fsm *fp, struct mbuf *bp) 896{ 897 int len; 898 struct fsmheader *lhp; 899 const struct fsmcodedesc *codep; 900 901 len = mbuf_Length(bp); 902 if (len < sizeof(struct fsmheader)) { 903 mbuf_Free(bp); 904 return; 905 } 906 lhp = (struct fsmheader *) MBUF_CTOP(bp); 907 if (lhp->code < fp->min_code || lhp->code > fp->max_code || 908 lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 909 /* 910 * Use a private id. This is really a response-type packet, but we 911 * MUST send a unique id for each REQ.... 912 */ 913 static u_char id; 914 915 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt); 916 mbuf_Free(bp); 917 return; 918 } 919 bp->offset += sizeof(struct fsmheader); 920 bp->cnt -= sizeof(struct fsmheader); 921 922 codep = FsmCodes + lhp->code - 1; 923 if (lhp->id != fp->reqid && codep->check_reqid && 924 Enabled(fp->bundle, OPT_IDCHECK)) { 925 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 926 fp->link->name, codep->name, lhp->id, fp->reqid); 927 return; 928 } 929 930 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 931 fp->link->name, codep->name, lhp->id, State2Nam(fp->state)); 932 933 if (log_IsKept(LogDEBUG)) 934 mbuf_Log(); 935 936 if (codep->inc_reqid && (lhp->id == fp->reqid || 937 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 938 fp->reqid++; /* That's the end of that ``exchange''.... */ 939 940 (*codep->recv)(fp, lhp, bp); 941 942 if (log_IsKept(LogDEBUG)) 943 mbuf_Log(); 944} 945 946void 947fsm_NullRecvResetReq(struct fsm *fp) 948{ 949 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 950 fp->link->name); 951} 952 953void 954fsm_NullRecvResetAck(struct fsm *fp, u_char id) 955{ 956 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 957 fp->link->name); 958} 959 960void 961fsm2initial(struct fsm *fp) 962{ 963 if (fp->state == ST_STOPPED) 964 fsm_Close(fp); 965 if (fp->state > ST_INITIAL) 966 fsm_Down(fp); 967 if (fp->state > ST_INITIAL) 968 fsm_Close(fp); 969} 970