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