fsm.c revision 37320
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.34 1998/06/27 23:48:43 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 if (fp->state != ST_STARTING) { 214 /* 215 * In practice, we're only here in ST_STOPPED (when delaying the 216 * first config request) or ST_CLOSED (when openmode == 0). 217 * 218 * The ST_STOPPED bit is breaking the RFC already :-( 219 * 220 * According to the RFC (1661) state transition table, a TLS isn't 221 * required for an Open event when state == Closed, but the RFC 222 * must be wrong as TLS hasn't yet been called (since the last TLF) 223 * ie, Initial gets an `Up' event, Closing gets a RTA etc. 224 */ 225 (*fp->fn->LayerStart)(fp); 226 (*fp->parent->LayerStart)(fp->parent->object, fp); 227 } 228 FsmInitRestartCounter(fp); 229 FsmSendConfigReq(fp); 230 NewState(fp, ST_REQSENT); 231 } 232} 233 234void 235fsm_Open(struct fsm * fp) 236{ 237 switch (fp->state) { 238 case ST_INITIAL: 239 NewState(fp, ST_STARTING); 240 (*fp->fn->LayerStart)(fp); 241 (*fp->parent->LayerStart)(fp->parent->object, fp); 242 break; 243 case ST_CLOSED: 244 if (fp->open_mode == OPEN_PASSIVE) { 245 NewState(fp, ST_STOPPED); /* XXX: This is a hack ! */ 246 } else if (fp->open_mode > 0) { 247 if (fp->open_mode > 1) 248 log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n", 249 fp->link->name, fp->open_mode); 250 NewState(fp, ST_STOPPED); /* XXX: This is a not-so-bad hack ! */ 251 timer_Stop(&fp->OpenTimer); 252 fp->OpenTimer.load = fp->open_mode * SECTICKS; 253 fp->OpenTimer.func = FsmOpenNow; 254 fp->OpenTimer.arg = (void *)fp; 255 timer_Start(&fp->OpenTimer); 256 } else 257 FsmOpenNow(fp); 258 break; 259 case ST_STOPPED: /* XXX: restart option */ 260 case ST_REQSENT: 261 case ST_ACKRCVD: 262 case ST_ACKSENT: 263 case ST_OPENED: /* XXX: restart option */ 264 break; 265 case ST_CLOSING: /* XXX: restart option */ 266 case ST_STOPPING: /* XXX: restart option */ 267 NewState(fp, ST_STOPPING); 268 break; 269 } 270} 271 272void 273fsm_Up(struct fsm * fp) 274{ 275 switch (fp->state) { 276 case ST_INITIAL: 277 log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n", 278 fp->link->name); 279 NewState(fp, ST_CLOSED); 280 break; 281 case ST_STARTING: 282 FsmInitRestartCounter(fp); 283 FsmSendConfigReq(fp); 284 NewState(fp, ST_REQSENT); 285 break; 286 default: 287 log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n", 288 fp->link->name, State2Nam(fp->state)); 289 break; 290 } 291} 292 293void 294fsm_Down(struct fsm *fp) 295{ 296 switch (fp->state) { 297 case ST_CLOSED: 298 NewState(fp, ST_INITIAL); 299 break; 300 case ST_CLOSING: 301 (*fp->fn->LayerFinish)(fp); 302 NewState(fp, ST_INITIAL); 303 (*fp->parent->LayerFinish)(fp->parent->object, fp); 304 break; 305 case ST_STOPPED: 306 NewState(fp, ST_STARTING); 307 (*fp->fn->LayerStart)(fp); 308 (*fp->parent->LayerStart)(fp->parent->object, fp); 309 break; 310 case ST_STOPPING: 311 case ST_REQSENT: 312 case ST_ACKRCVD: 313 case ST_ACKSENT: 314 NewState(fp, ST_STARTING); 315 break; 316 case ST_OPENED: 317 (*fp->fn->LayerDown)(fp); 318 NewState(fp, ST_STARTING); 319 (*fp->parent->LayerDown)(fp->parent->object, fp); 320 break; 321 } 322} 323 324void 325fsm_Close(struct fsm *fp) 326{ 327 switch (fp->state) { 328 case ST_STARTING: 329 (*fp->fn->LayerFinish)(fp); 330 NewState(fp, ST_INITIAL); 331 (*fp->parent->LayerFinish)(fp->parent->object, fp); 332 break; 333 case ST_STOPPED: 334 NewState(fp, ST_CLOSED); 335 break; 336 case ST_STOPPING: 337 NewState(fp, ST_CLOSING); 338 break; 339 case ST_OPENED: 340 (*fp->fn->LayerDown)(fp); 341 FsmInitRestartCounter(fp); 342 FsmSendTerminateReq(fp); 343 NewState(fp, ST_CLOSING); 344 (*fp->parent->LayerDown)(fp->parent->object, fp); 345 break; 346 case ST_REQSENT: 347 case ST_ACKRCVD: 348 case ST_ACKSENT: 349 FsmInitRestartCounter(fp); 350 FsmSendTerminateReq(fp); 351 NewState(fp, ST_CLOSING); 352 break; 353 } 354} 355 356/* 357 * Send functions 358 */ 359static void 360FsmSendConfigReq(struct fsm * fp) 361{ 362 if (--fp->maxconfig > 0) { 363 (*fp->fn->SendConfigReq)(fp); 364 timer_Start(&fp->FsmTimer); /* Start restart timer */ 365 fp->restart--; /* Decrement restart counter */ 366 } else { 367 fsm_Close(fp); 368 } 369} 370 371static void 372FsmSendTerminateReq(struct fsm *fp) 373{ 374 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 375 (*fp->fn->SentTerminateReq)(fp); 376 timer_Start(&fp->FsmTimer); /* Start restart timer */ 377 fp->restart--; /* Decrement restart counter */ 378} 379 380/* 381 * Timeout actions 382 */ 383static void 384FsmTimeout(void *v) 385{ 386 struct fsm *fp = (struct fsm *)v; 387 388 if (fp->restart) { 389 switch (fp->state) { 390 case ST_CLOSING: 391 case ST_STOPPING: 392 FsmSendTerminateReq(fp); 393 break; 394 case ST_REQSENT: 395 case ST_ACKSENT: 396 FsmSendConfigReq(fp); 397 break; 398 case ST_ACKRCVD: 399 FsmSendConfigReq(fp); 400 NewState(fp, ST_REQSENT); 401 break; 402 } 403 timer_Start(&fp->FsmTimer); 404 } else { 405 switch (fp->state) { 406 case ST_CLOSING: 407 (*fp->fn->LayerFinish)(fp); 408 NewState(fp, ST_CLOSED); 409 (*fp->parent->LayerFinish)(fp->parent->object, fp); 410 break; 411 case ST_STOPPING: 412 (*fp->fn->LayerFinish)(fp); 413 NewState(fp, ST_STOPPED); 414 (*fp->parent->LayerFinish)(fp->parent->object, fp); 415 break; 416 case ST_REQSENT: /* XXX: 3p */ 417 case ST_ACKSENT: 418 case ST_ACKRCVD: 419 (*fp->fn->LayerFinish)(fp); 420 NewState(fp, ST_STOPPED); 421 (*fp->parent->LayerFinish)(fp->parent->object, fp); 422 break; 423 } 424 } 425} 426 427static void 428FsmInitRestartCounter(struct fsm * fp) 429{ 430 timer_Stop(&fp->FsmTimer); 431 fp->FsmTimer.func = FsmTimeout; 432 fp->FsmTimer.arg = (void *) fp; 433 (*fp->fn->InitRestartCounter)(fp); 434} 435 436/* 437 * Actions when receive packets 438 */ 439static void 440FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 441/* RCR */ 442{ 443 struct fsm_decode dec; 444 int plen, flen; 445 int ackaction = 0; 446 447 plen = mbuf_Length(bp); 448 flen = ntohs(lhp->length) - sizeof *lhp; 449 if (plen < flen) { 450 log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 451 fp->link->name, plen, flen); 452 mbuf_Free(bp); 453 return; 454 } 455 456 /* 457 * Check and process easy case 458 */ 459 switch (fp->state) { 460 case ST_INITIAL: 461 if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) { 462 /* 463 * ccp_SetOpenMode() leaves us in initial if we're disabling 464 * & denying everything. This is a bit smelly, we know that 465 * ``bp'' really has ``fsmheader'' in front of it, and CCP_PROTO 466 * in front of that. CCP_PROTO isn't compressed either 'cos it 467 * doesn't begin with 0x00.... 468 */ 469 bp->offset -= sizeof(struct fsmheader) + 2; 470 bp->cnt += sizeof(struct fsmheader) + 2; 471 lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->cnt); 472 mbuf_Free(bp); 473 return; 474 } 475 /* Drop through */ 476 case ST_STARTING: 477 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 478 fp->link->name, State2Nam(fp->state)); 479 mbuf_Free(bp); 480 return; 481 case ST_CLOSED: 482 (*fp->fn->SendTerminateAck)(fp, lhp->id); 483 mbuf_Free(bp); 484 return; 485 case ST_CLOSING: 486 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 487 fp->link->name, State2Nam(fp->state)); 488 case ST_STOPPING: 489 mbuf_Free(bp); 490 return; 491 } 492 493 dec.ackend = dec.ack; 494 dec.nakend = dec.nak; 495 dec.rejend = dec.rej; 496 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 497 if (flen < sizeof(struct fsmconfig)) 498 log_Printf(fp->LogLevel, " [EMPTY]\n"); 499 500 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 501 ackaction = 1; 502 503 switch (fp->state) { 504 case ST_OPENED: 505 (*fp->fn->LayerDown)(fp); 506 FsmSendConfigReq(fp); 507 (*fp->parent->LayerDown)(fp->parent->object, fp); 508 break; 509 case ST_STOPPED: 510 FsmInitRestartCounter(fp); 511 FsmSendConfigReq(fp); 512 break; 513 } 514 515 if (dec.rejend != dec.rej) 516 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 517 if (dec.nakend != dec.nak) 518 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 519 if (ackaction) 520 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 521 522 switch (fp->state) { 523 case ST_OPENED: 524 case ST_STOPPED: 525 if (ackaction) 526 NewState(fp, ST_ACKSENT); 527 else 528 NewState(fp, ST_REQSENT); 529 break; 530 case ST_REQSENT: 531 if (ackaction) 532 NewState(fp, ST_ACKSENT); 533 break; 534 case ST_ACKRCVD: 535 if (ackaction) { 536 NewState(fp, ST_OPENED); 537 if ((*fp->fn->LayerUp)(fp)) 538 (*fp->parent->LayerUp)(fp->parent->object, fp); 539 else { 540 (*fp->fn->LayerDown)(fp); 541 FsmInitRestartCounter(fp); 542 FsmSendTerminateReq(fp); 543 NewState(fp, ST_CLOSING); 544 } 545 } 546 break; 547 case ST_ACKSENT: 548 if (!ackaction) 549 NewState(fp, ST_REQSENT); 550 break; 551 } 552 mbuf_Free(bp); 553} 554 555static void 556FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 557/* RCA */ 558{ 559 switch (fp->state) { 560 case ST_CLOSED: 561 case ST_STOPPED: 562 (*fp->fn->SendTerminateAck)(fp, lhp->id); 563 break; 564 case ST_CLOSING: 565 case ST_STOPPING: 566 break; 567 case ST_REQSENT: 568 FsmInitRestartCounter(fp); 569 NewState(fp, ST_ACKRCVD); 570 break; 571 case ST_ACKRCVD: 572 FsmSendConfigReq(fp); 573 NewState(fp, ST_REQSENT); 574 break; 575 case ST_ACKSENT: 576 FsmInitRestartCounter(fp); 577 NewState(fp, ST_OPENED); 578 if ((*fp->fn->LayerUp)(fp)) 579 (*fp->parent->LayerUp)(fp->parent->object, fp); 580 else { 581 (*fp->fn->LayerDown)(fp); 582 FsmInitRestartCounter(fp); 583 FsmSendTerminateReq(fp); 584 NewState(fp, ST_CLOSING); 585 } 586 break; 587 case ST_OPENED: 588 (*fp->fn->LayerDown)(fp); 589 FsmSendConfigReq(fp); 590 NewState(fp, ST_REQSENT); 591 (*fp->parent->LayerDown)(fp->parent->object, fp); 592 break; 593 } 594 mbuf_Free(bp); 595} 596 597static void 598FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 599/* RCN */ 600{ 601 struct fsm_decode dec; 602 int plen, flen; 603 604 plen = mbuf_Length(bp); 605 flen = ntohs(lhp->length) - sizeof *lhp; 606 if (plen < flen) { 607 mbuf_Free(bp); 608 return; 609 } 610 611 /* 612 * Check and process easy case 613 */ 614 switch (fp->state) { 615 case ST_INITIAL: 616 case ST_STARTING: 617 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 618 fp->link->name, State2Nam(fp->state)); 619 mbuf_Free(bp); 620 return; 621 case ST_CLOSED: 622 case ST_STOPPED: 623 (*fp->fn->SendTerminateAck)(fp, lhp->id); 624 mbuf_Free(bp); 625 return; 626 case ST_CLOSING: 627 case ST_STOPPING: 628 mbuf_Free(bp); 629 return; 630 } 631 632 dec.ackend = dec.ack; 633 dec.nakend = dec.nak; 634 dec.rejend = dec.rej; 635 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 636 if (flen < sizeof(struct fsmconfig)) 637 log_Printf(fp->LogLevel, " [EMPTY]\n"); 638 639 switch (fp->state) { 640 case ST_REQSENT: 641 case ST_ACKSENT: 642 FsmInitRestartCounter(fp); 643 FsmSendConfigReq(fp); 644 break; 645 case ST_OPENED: 646 (*fp->fn->LayerDown)(fp); 647 FsmSendConfigReq(fp); 648 NewState(fp, ST_REQSENT); 649 (*fp->parent->LayerDown)(fp->parent->object, fp); 650 break; 651 case ST_ACKRCVD: 652 FsmSendConfigReq(fp); 653 NewState(fp, ST_REQSENT); 654 break; 655 } 656 657 mbuf_Free(bp); 658} 659 660static void 661FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 662/* RTR */ 663{ 664 switch (fp->state) { 665 case ST_INITIAL: 666 case ST_STARTING: 667 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 668 fp->link->name, State2Nam(fp->state)); 669 break; 670 case ST_CLOSED: 671 case ST_STOPPED: 672 case ST_CLOSING: 673 case ST_STOPPING: 674 case ST_REQSENT: 675 (*fp->fn->SendTerminateAck)(fp, lhp->id); 676 break; 677 case ST_ACKRCVD: 678 case ST_ACKSENT: 679 (*fp->fn->SendTerminateAck)(fp, lhp->id); 680 NewState(fp, ST_REQSENT); 681 break; 682 case ST_OPENED: 683 (*fp->fn->LayerDown)(fp); 684 (*fp->fn->SendTerminateAck)(fp, lhp->id); 685 FsmInitRestartCounter(fp); 686 timer_Start(&fp->FsmTimer); /* Start restart timer */ 687 fp->restart = 0; 688 NewState(fp, ST_STOPPING); 689 (*fp->parent->LayerDown)(fp->parent->object, fp); 690 break; 691 } 692 mbuf_Free(bp); 693} 694 695static void 696FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 697/* RTA */ 698{ 699 switch (fp->state) { 700 case ST_CLOSING: 701 (*fp->fn->LayerFinish)(fp); 702 NewState(fp, ST_CLOSED); 703 (*fp->parent->LayerFinish)(fp->parent->object, fp); 704 break; 705 case ST_STOPPING: 706 (*fp->fn->LayerFinish)(fp); 707 NewState(fp, ST_STOPPED); 708 (*fp->parent->LayerFinish)(fp->parent->object, fp); 709 break; 710 case ST_ACKRCVD: 711 NewState(fp, ST_REQSENT); 712 break; 713 case ST_OPENED: 714 (*fp->fn->LayerDown)(fp); 715 FsmSendConfigReq(fp); 716 NewState(fp, ST_REQSENT); 717 (*fp->parent->LayerDown)(fp->parent->object, fp); 718 break; 719 } 720 mbuf_Free(bp); 721} 722 723static void 724FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 725/* RCJ */ 726{ 727 struct fsm_decode dec; 728 int plen, flen; 729 730 plen = mbuf_Length(bp); 731 flen = ntohs(lhp->length) - sizeof *lhp; 732 if (plen < flen) { 733 mbuf_Free(bp); 734 return; 735 } 736 737 /* 738 * Check and process easy case 739 */ 740 switch (fp->state) { 741 case ST_INITIAL: 742 case ST_STARTING: 743 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 744 fp->link->name, State2Nam(fp->state)); 745 mbuf_Free(bp); 746 return; 747 case ST_CLOSED: 748 case ST_STOPPED: 749 (*fp->fn->SendTerminateAck)(fp, lhp->id); 750 mbuf_Free(bp); 751 return; 752 case ST_CLOSING: 753 case ST_STOPPING: 754 mbuf_Free(bp); 755 return; 756 } 757 758 dec.ackend = dec.ack; 759 dec.nakend = dec.nak; 760 dec.rejend = dec.rej; 761 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 762 if (flen < sizeof(struct fsmconfig)) 763 log_Printf(fp->LogLevel, " [EMPTY]\n"); 764 765 switch (fp->state) { 766 case ST_REQSENT: 767 case ST_ACKSENT: 768 FsmInitRestartCounter(fp); 769 FsmSendConfigReq(fp); 770 break; 771 case ST_OPENED: 772 (*fp->fn->LayerDown)(fp); 773 FsmSendConfigReq(fp); 774 NewState(fp, ST_REQSENT); 775 (*fp->parent->LayerDown)(fp->parent->object, fp); 776 break; 777 case ST_ACKRCVD: 778 FsmSendConfigReq(fp); 779 NewState(fp, ST_REQSENT); 780 break; 781 } 782 mbuf_Free(bp); 783} 784 785static void 786FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 787{ 788 mbuf_Free(bp); 789} 790 791static void 792FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 793{ 794 struct physical *p = link2physical(fp->link); 795 u_short *sp, proto; 796 797 sp = (u_short *)MBUF_CTOP(bp); 798 proto = ntohs(*sp); 799 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 800 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 801 802 switch (proto) { 803 case PROTO_LQR: 804 if (p) 805 lqr_Stop(p, LQM_LQR); 806 else 807 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 808 fp->link->name); 809 break; 810 case PROTO_CCP: 811 if (fp->proto == PROTO_LCP) { 812 fp = &fp->link->ccp.fsm; 813 (*fp->fn->LayerFinish)(fp); 814 switch (fp->state) { 815 case ST_CLOSED: 816 case ST_CLOSING: 817 NewState(fp, ST_CLOSED); 818 default: 819 NewState(fp, ST_STOPPED); 820 break; 821 } 822 (*fp->parent->LayerFinish)(fp->parent->object, fp); 823 } 824 break; 825 case PROTO_MP: 826 if (fp->proto == PROTO_LCP) { 827 struct lcp *lcp = fsm2lcp(fp); 828 829 if (lcp->want_mrru && lcp->his_mrru) { 830 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 831 fp->link->name); 832 fsm_Close(fp); 833 } 834 } 835 break; 836 } 837 mbuf_Free(bp); 838} 839 840static void 841FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 842{ 843 struct lcp *lcp = fsm2lcp(fp); 844 u_char *cp; 845 u_int32_t magic; 846 847 if (lcp) { 848 cp = MBUF_CTOP(bp); 849 magic = ntohl(*(u_int32_t *)cp); 850 if (magic != lcp->his_magic) { 851 log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n", 852 fp->link->name); 853 /* XXX: We should send terminate request */ 854 } 855 if (fp->state == ST_OPENED) { 856 *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */ 857 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp)); 858 } 859 } 860 mbuf_Free(bp); 861} 862 863static void 864FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 865{ 866 struct lcp *lcp = fsm2lcp(fp); 867 u_int32_t magic; 868 869 if (lcp) { 870 magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp)); 871 /* Tolerate echo replies with either magic number */ 872 if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 873 log_Printf(LogWARN, 874 "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 875 fp->link->name, lcp->his_magic, magic); 876 /* 877 * XXX: We should send terminate request. But poor implementations may 878 * die as a result. 879 */ 880 } 881 lqr_RecvEcho(fp, bp); 882 } 883 mbuf_Free(bp); 884} 885 886static void 887FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 888{ 889 mbuf_Free(bp); 890} 891 892static void 893FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 894{ 895 mbuf_Free(bp); 896} 897 898static void 899FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 900{ 901 mbuf_Free(bp); 902} 903 904static void 905FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 906{ 907 (*fp->fn->RecvResetReq)(fp); 908 /* 909 * All sendable compressed packets are queued in the PRI_NORMAL modem 910 * output queue.... dump 'em to the priority queue so that they arrive 911 * at the peer before our ResetAck. 912 */ 913 link_SequenceQueue(fp->link); 914 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0); 915 mbuf_Free(bp); 916} 917 918static void 919FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 920{ 921 (*fp->fn->RecvResetAck)(fp, lhp->id); 922 mbuf_Free(bp); 923} 924 925void 926fsm_Input(struct fsm *fp, struct mbuf *bp) 927{ 928 int len; 929 struct fsmheader *lhp; 930 const struct fsmcodedesc *codep; 931 932 len = mbuf_Length(bp); 933 if (len < sizeof(struct fsmheader)) { 934 mbuf_Free(bp); 935 return; 936 } 937 lhp = (struct fsmheader *) MBUF_CTOP(bp); 938 if (lhp->code < fp->min_code || lhp->code > fp->max_code || 939 lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 940 /* 941 * Use a private id. This is really a response-type packet, but we 942 * MUST send a unique id for each REQ.... 943 */ 944 static u_char id; 945 946 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt); 947 mbuf_Free(bp); 948 return; 949 } 950 bp->offset += sizeof(struct fsmheader); 951 bp->cnt -= sizeof(struct fsmheader); 952 953 codep = FsmCodes + lhp->code - 1; 954 if (lhp->id != fp->reqid && codep->check_reqid && 955 Enabled(fp->bundle, OPT_IDCHECK)) { 956 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 957 fp->link->name, codep->name, lhp->id, fp->reqid); 958 return; 959 } 960 961 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 962 fp->link->name, codep->name, lhp->id, State2Nam(fp->state)); 963 964 if (log_IsKept(LogDEBUG)) 965 mbuf_Log(); 966 967 if (codep->inc_reqid && (lhp->id == fp->reqid || 968 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 969 fp->reqid++; /* That's the end of that ``exchange''.... */ 970 971 (*codep->recv)(fp, lhp, bp); 972 973 if (log_IsKept(LogDEBUG)) 974 mbuf_Log(); 975} 976 977void 978fsm_NullRecvResetReq(struct fsm *fp) 979{ 980 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 981 fp->link->name); 982} 983 984void 985fsm_NullRecvResetAck(struct fsm *fp, u_char id) 986{ 987 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 988 fp->link->name); 989} 990 991void 992fsm_Reopen(struct fsm *fp) 993{ 994 if (fp->state == ST_OPENED) { 995 (*fp->fn->LayerDown)(fp); 996 FsmInitRestartCounter(fp); 997 FsmSendConfigReq(fp); 998 NewState(fp, ST_REQSENT); 999 (*fp->parent->LayerDown)(fp->parent->object, fp); 1000 } 1001} 1002 1003void 1004fsm2initial(struct fsm *fp) 1005{ 1006 if (fp->state == ST_STOPPED) 1007 fsm_Close(fp); 1008 if (fp->state > ST_INITIAL) 1009 fsm_Down(fp); 1010 if (fp->state > ST_INITIAL) 1011 fsm_Close(fp); 1012} 1013