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