NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
fsm.c
00001 /***************************************************************************** 00002 * fsm.c - Network Control Protocol Finite State Machine program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * portions Copyright (c) 1997 by Global Election Systems Inc. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Original based on BSD fsm.c. 00032 *****************************************************************************/ 00033 /* 00034 * fsm.c - {Link, IP} Control Protocol Finite State Machine. 00035 * 00036 * Copyright (c) 1989 Carnegie Mellon University. 00037 * All rights reserved. 00038 * 00039 * Redistribution and use in source and binary forms are permitted 00040 * provided that the above copyright notice and this paragraph are 00041 * duplicated in all such forms and that any documentation, 00042 * advertising materials, and other materials related to such 00043 * distribution and use acknowledge that the software was developed 00044 * by Carnegie Mellon University. The name of the 00045 * University may not be used to endorse or promote products derived 00046 * from this software without specific prior written permission. 00047 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00048 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00049 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00050 */ 00051 00052 /* 00053 * TODO: 00054 * Randomize fsm id on link/init. 00055 * Deal with variable outgoing MTU. 00056 */ 00057 00058 #include "lwip/opt.h" 00059 00060 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00061 00062 #include "ppp.h" 00063 #include "pppdebug.h" 00064 00065 #include "fsm.h" 00066 00067 #include <string.h> 00068 00069 #if PPP_DEBUG 00070 static const char *ppperr_strerr[] = { 00071 "LS_INITIAL", /* LS_INITIAL 0 */ 00072 "LS_STARTING", /* LS_STARTING 1 */ 00073 "LS_CLOSED", /* LS_CLOSED 2 */ 00074 "LS_STOPPED", /* LS_STOPPED 3 */ 00075 "LS_CLOSING", /* LS_CLOSING 4 */ 00076 "LS_STOPPING", /* LS_STOPPING 5 */ 00077 "LS_REQSENT", /* LS_REQSENT 6 */ 00078 "LS_ACKRCVD", /* LS_ACKRCVD 7 */ 00079 "LS_ACKSENT", /* LS_ACKSENT 8 */ 00080 "LS_OPENED" /* LS_OPENED 9 */ 00081 }; 00082 #endif /* PPP_DEBUG */ 00083 00084 static void fsm_timeout (void *); 00085 static void fsm_rconfreq (fsm *, u_char, u_char *, int); 00086 static void fsm_rconfack (fsm *, int, u_char *, int); 00087 static void fsm_rconfnakrej (fsm *, int, int, u_char *, int); 00088 static void fsm_rtermreq (fsm *, int, u_char *, int); 00089 static void fsm_rtermack (fsm *); 00090 static void fsm_rcoderej (fsm *, u_char *, int); 00091 static void fsm_sconfreq (fsm *, int); 00092 00093 #define PROTO_NAME(f) ((f)->callbacks->proto_name) 00094 00095 int peer_mru[NUM_PPP]; 00096 00097 00098 /* 00099 * fsm_init - Initialize fsm. 00100 * 00101 * Initialize fsm state. 00102 */ 00103 void 00104 fsm_init(fsm *f) 00105 { 00106 f->state = LS_INITIAL; 00107 f->flags = 0; 00108 f->id = 0; /* XXX Start with random id? */ 00109 f->timeouttime = FSM_DEFTIMEOUT; 00110 f->maxconfreqtransmits = FSM_DEFMAXCONFREQS; 00111 f->maxtermtransmits = FSM_DEFMAXTERMREQS; 00112 f->maxnakloops = FSM_DEFMAXNAKLOOPS; 00113 f->term_reason_len = 0; 00114 } 00115 00116 00117 /* 00118 * fsm_lowerup - The lower layer is up. 00119 */ 00120 void 00121 fsm_lowerup(fsm *f) 00122 { 00123 int oldState = f->state; 00124 00125 LWIP_UNUSED_ARG(oldState); 00126 00127 switch( f->state ) { 00128 case LS_INITIAL: 00129 f->state = LS_CLOSED; 00130 break; 00131 00132 case LS_STARTING: 00133 if( f->flags & OPT_SILENT ) { 00134 f->state = LS_STOPPED; 00135 } else { 00136 /* Send an initial configure-request */ 00137 fsm_sconfreq(f, 0); 00138 f->state = LS_REQSENT; 00139 } 00140 break; 00141 00142 default: 00143 FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", 00144 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00145 } 00146 00147 FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", 00148 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00149 } 00150 00151 00152 /* 00153 * fsm_lowerdown - The lower layer is down. 00154 * 00155 * Cancel all timeouts and inform upper layers. 00156 */ 00157 void 00158 fsm_lowerdown(fsm *f) 00159 { 00160 int oldState = f->state; 00161 00162 LWIP_UNUSED_ARG(oldState); 00163 00164 switch( f->state ) { 00165 case LS_CLOSED: 00166 f->state = LS_INITIAL; 00167 break; 00168 00169 case LS_STOPPED: 00170 f->state = LS_STARTING; 00171 if( f->callbacks->starting ) { 00172 (*f->callbacks->starting)(f); 00173 } 00174 break; 00175 00176 case LS_CLOSING: 00177 f->state = LS_INITIAL; 00178 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00179 break; 00180 00181 case LS_STOPPING: 00182 case LS_REQSENT: 00183 case LS_ACKRCVD: 00184 case LS_ACKSENT: 00185 f->state = LS_STARTING; 00186 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00187 break; 00188 00189 case LS_OPENED: 00190 if( f->callbacks->down ) { 00191 (*f->callbacks->down)(f); 00192 } 00193 f->state = LS_STARTING; 00194 break; 00195 00196 default: 00197 FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", 00198 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00199 } 00200 00201 FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", 00202 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00203 } 00204 00205 00206 /* 00207 * fsm_open - Link is allowed to come up. 00208 */ 00209 void 00210 fsm_open(fsm *f) 00211 { 00212 int oldState = f->state; 00213 00214 LWIP_UNUSED_ARG(oldState); 00215 00216 switch( f->state ) { 00217 case LS_INITIAL: 00218 f->state = LS_STARTING; 00219 if( f->callbacks->starting ) { 00220 (*f->callbacks->starting)(f); 00221 } 00222 break; 00223 00224 case LS_CLOSED: 00225 if( f->flags & OPT_SILENT ) { 00226 f->state = LS_STOPPED; 00227 } else { 00228 /* Send an initial configure-request */ 00229 fsm_sconfreq(f, 0); 00230 f->state = LS_REQSENT; 00231 } 00232 break; 00233 00234 case LS_CLOSING: 00235 f->state = LS_STOPPING; 00236 /* fall through */ 00237 case LS_STOPPED: 00238 case LS_OPENED: 00239 if( f->flags & OPT_RESTART ) { 00240 fsm_lowerdown(f); 00241 fsm_lowerup(f); 00242 } 00243 break; 00244 } 00245 00246 FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", 00247 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00248 } 00249 00250 #if 0 /* backport pppd 2.4.4b1; */ 00251 /* 00252 * terminate_layer - Start process of shutting down the FSM 00253 * 00254 * Cancel any timeout running, notify upper layers we're done, and 00255 * send a terminate-request message as configured. 00256 */ 00257 static void 00258 terminate_layer(fsm *f, int nextstate) 00259 { 00260 /* @todo */ 00261 } 00262 #endif 00263 00264 /* 00265 * fsm_close - Start closing connection. 00266 * 00267 * Cancel timeouts and either initiate close or possibly go directly to 00268 * the LS_CLOSED state. 00269 */ 00270 void 00271 fsm_close(fsm *f, char *reason) 00272 { 00273 int oldState = f->state; 00274 00275 LWIP_UNUSED_ARG(oldState); 00276 00277 f->term_reason = reason; 00278 f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason)); 00279 switch( f->state ) { 00280 case LS_STARTING: 00281 f->state = LS_INITIAL; 00282 break; 00283 case LS_STOPPED: 00284 f->state = LS_CLOSED; 00285 break; 00286 case LS_STOPPING: 00287 f->state = LS_CLOSING; 00288 break; 00289 00290 case LS_REQSENT: 00291 case LS_ACKRCVD: 00292 case LS_ACKSENT: 00293 case LS_OPENED: 00294 if( f->state != LS_OPENED ) { 00295 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00296 } else if( f->callbacks->down ) { 00297 (*f->callbacks->down)(f); /* Inform upper layers we're down */ 00298 } 00299 /* Init restart counter, send Terminate-Request */ 00300 f->retransmits = f->maxtermtransmits; 00301 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00302 (u_char *) f->term_reason, f->term_reason_len); 00303 TIMEOUT(fsm_timeout, f, f->timeouttime); 00304 --f->retransmits; 00305 00306 f->state = LS_CLOSING; 00307 break; 00308 } 00309 00310 FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", 00311 PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00312 } 00313 00314 00315 /* 00316 * fsm_timeout - Timeout expired. 00317 */ 00318 static void 00319 fsm_timeout(void *arg) 00320 { 00321 fsm *f = (fsm *) arg; 00322 00323 switch (f->state) { 00324 case LS_CLOSING: 00325 case LS_STOPPING: 00326 if( f->retransmits <= 0 ) { 00327 FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", 00328 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00329 /* 00330 * We've waited for an ack long enough. Peer probably heard us. 00331 */ 00332 f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; 00333 if( f->callbacks->finished ) { 00334 (*f->callbacks->finished)(f); 00335 } 00336 } else { 00337 FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", 00338 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00339 /* Send Terminate-Request */ 00340 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00341 (u_char *) f->term_reason, f->term_reason_len); 00342 TIMEOUT(fsm_timeout, f, f->timeouttime); 00343 --f->retransmits; 00344 } 00345 break; 00346 00347 case LS_REQSENT: 00348 case LS_ACKRCVD: 00349 case LS_ACKSENT: 00350 if (f->retransmits <= 0) { 00351 FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", 00352 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00353 f->state = LS_STOPPED; 00354 if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { 00355 (*f->callbacks->finished)(f); 00356 } 00357 } else { 00358 FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", 00359 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00360 /* Retransmit the configure-request */ 00361 if (f->callbacks->retransmit) { 00362 (*f->callbacks->retransmit)(f); 00363 } 00364 fsm_sconfreq(f, 1); /* Re-send Configure-Request */ 00365 if( f->state == LS_ACKRCVD ) { 00366 f->state = LS_REQSENT; 00367 } 00368 } 00369 break; 00370 00371 default: 00372 FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", 00373 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00374 } 00375 } 00376 00377 00378 /* 00379 * fsm_input - Input packet. 00380 */ 00381 void 00382 fsm_input(fsm *f, u_char *inpacket, int l) 00383 { 00384 u_char *inp = inpacket; 00385 u_char code, id; 00386 int len; 00387 00388 /* 00389 * Parse header (code, id and length). 00390 * If packet too short, drop it. 00391 */ 00392 if (l < HEADERLEN) { 00393 FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", 00394 f->protocol)); 00395 return; 00396 } 00397 GETCHAR(code, inp); 00398 GETCHAR(id, inp); 00399 GETSHORT(len, inp); 00400 if (len < HEADERLEN) { 00401 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", 00402 f->protocol)); 00403 return; 00404 } 00405 if (len > l) { 00406 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", 00407 f->protocol)); 00408 return; 00409 } 00410 len -= HEADERLEN; /* subtract header length */ 00411 00412 if( f->state == LS_INITIAL || f->state == LS_STARTING ) { 00413 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", 00414 f->protocol, f->state, ppperr_strerr[f->state])); 00415 return; 00416 } 00417 FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); 00418 /* 00419 * Action depends on code. 00420 */ 00421 switch (code) { 00422 case CONFREQ: 00423 fsm_rconfreq(f, id, inp, len); 00424 break; 00425 00426 case CONFACK: 00427 fsm_rconfack(f, id, inp, len); 00428 break; 00429 00430 case CONFNAK: 00431 case CONFREJ: 00432 fsm_rconfnakrej(f, code, id, inp, len); 00433 break; 00434 00435 case TERMREQ: 00436 fsm_rtermreq(f, id, inp, len); 00437 break; 00438 00439 case TERMACK: 00440 fsm_rtermack(f); 00441 break; 00442 00443 case CODEREJ: 00444 fsm_rcoderej(f, inp, len); 00445 break; 00446 00447 default: 00448 FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); 00449 if( !f->callbacks->extcode || 00450 !(*f->callbacks->extcode)(f, code, id, inp, len) ) { 00451 fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); 00452 } 00453 break; 00454 } 00455 } 00456 00457 00458 /* 00459 * fsm_rconfreq - Receive Configure-Request. 00460 */ 00461 static void 00462 fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) 00463 { 00464 int code, reject_if_disagree; 00465 00466 FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", 00467 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00468 switch( f->state ) { 00469 case LS_CLOSED: 00470 /* Go away, we're closed */ 00471 fsm_sdata(f, TERMACK, id, NULL, 0); 00472 return; 00473 case LS_CLOSING: 00474 case LS_STOPPING: 00475 return; 00476 00477 case LS_OPENED: 00478 /* Go down and restart negotiation */ 00479 if( f->callbacks->down ) { 00480 (*f->callbacks->down)(f); /* Inform upper layers */ 00481 } 00482 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00483 break; 00484 00485 case LS_STOPPED: 00486 /* Negotiation started by our peer */ 00487 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00488 f->state = LS_REQSENT; 00489 break; 00490 } 00491 00492 /* 00493 * Pass the requested configuration options 00494 * to protocol-specific code for checking. 00495 */ 00496 if (f->callbacks->reqci) { /* Check CI */ 00497 reject_if_disagree = (f->nakloops >= f->maxnakloops); 00498 code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); 00499 } else if (len) { 00500 code = CONFREJ; /* Reject all CI */ 00501 } else { 00502 code = CONFACK; 00503 } 00504 00505 /* send the Ack, Nak or Rej to the peer */ 00506 fsm_sdata(f, (u_char)code, id, inp, len); 00507 00508 if (code == CONFACK) { 00509 if (f->state == LS_ACKRCVD) { 00510 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00511 f->state = LS_OPENED; 00512 if (f->callbacks->up) { 00513 (*f->callbacks->up)(f); /* Inform upper layers */ 00514 } 00515 } else { 00516 f->state = LS_ACKSENT; 00517 } 00518 f->nakloops = 0; 00519 } else { 00520 /* we sent CONFACK or CONFREJ */ 00521 if (f->state != LS_ACKRCVD) { 00522 f->state = LS_REQSENT; 00523 } 00524 if( code == CONFNAK ) { 00525 ++f->nakloops; 00526 } 00527 } 00528 } 00529 00530 00531 /* 00532 * fsm_rconfack - Receive Configure-Ack. 00533 */ 00534 static void 00535 fsm_rconfack(fsm *f, int id, u_char *inp, int len) 00536 { 00537 FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", 00538 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00539 00540 if (id != f->reqid || f->seen_ack) { /* Expected id? */ 00541 return; /* Nope, toss... */ 00542 } 00543 if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { 00544 /* Ack is bad - ignore it */ 00545 FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", 00546 PROTO_NAME(f), len)); 00547 return; 00548 } 00549 f->seen_ack = 1; 00550 00551 switch (f->state) { 00552 case LS_CLOSED: 00553 case LS_STOPPED: 00554 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 00555 break; 00556 00557 case LS_REQSENT: 00558 f->state = LS_ACKRCVD; 00559 f->retransmits = f->maxconfreqtransmits; 00560 break; 00561 00562 case LS_ACKRCVD: 00563 /* Huh? an extra valid Ack? oh well... */ 00564 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00565 fsm_sconfreq(f, 0); 00566 f->state = LS_REQSENT; 00567 break; 00568 00569 case LS_ACKSENT: 00570 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00571 f->state = LS_OPENED; 00572 f->retransmits = f->maxconfreqtransmits; 00573 if (f->callbacks->up) { 00574 (*f->callbacks->up)(f); /* Inform upper layers */ 00575 } 00576 break; 00577 00578 case LS_OPENED: 00579 /* Go down and restart negotiation */ 00580 if (f->callbacks->down) { 00581 (*f->callbacks->down)(f); /* Inform upper layers */ 00582 } 00583 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00584 f->state = LS_REQSENT; 00585 break; 00586 } 00587 } 00588 00589 00590 /* 00591 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 00592 */ 00593 static void 00594 fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) 00595 { 00596 int (*proc) (fsm *, u_char *, int); 00597 int ret; 00598 00599 FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", 00600 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00601 00602 if (id != f->reqid || f->seen_ack) { /* Expected id? */ 00603 return; /* Nope, toss... */ 00604 } 00605 proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; 00606 if (!proc || !((ret = proc(f, inp, len)))) { 00607 /* Nak/reject is bad - ignore it */ 00608 FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", 00609 PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); 00610 return; 00611 } 00612 f->seen_ack = 1; 00613 00614 switch (f->state) { 00615 case LS_CLOSED: 00616 case LS_STOPPED: 00617 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 00618 break; 00619 00620 case LS_REQSENT: 00621 case LS_ACKSENT: 00622 /* They didn't agree to what we wanted - try another request */ 00623 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00624 if (ret < 0) { 00625 f->state = LS_STOPPED; /* kludge for stopping CCP */ 00626 } else { 00627 fsm_sconfreq(f, 0); /* Send Configure-Request */ 00628 } 00629 break; 00630 00631 case LS_ACKRCVD: 00632 /* Got a Nak/reject when we had already had an Ack?? oh well... */ 00633 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00634 fsm_sconfreq(f, 0); 00635 f->state = LS_REQSENT; 00636 break; 00637 00638 case LS_OPENED: 00639 /* Go down and restart negotiation */ 00640 if (f->callbacks->down) { 00641 (*f->callbacks->down)(f); /* Inform upper layers */ 00642 } 00643 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00644 f->state = LS_REQSENT; 00645 break; 00646 } 00647 } 00648 00649 00650 /* 00651 * fsm_rtermreq - Receive Terminate-Req. 00652 */ 00653 static void 00654 fsm_rtermreq(fsm *f, int id, u_char *p, int len) 00655 { 00656 LWIP_UNUSED_ARG(p); 00657 00658 FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", 00659 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00660 00661 switch (f->state) { 00662 case LS_ACKRCVD: 00663 case LS_ACKSENT: 00664 f->state = LS_REQSENT; /* Start over but keep trying */ 00665 break; 00666 00667 case LS_OPENED: 00668 if (len > 0) { 00669 FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); 00670 } else { 00671 FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); 00672 } 00673 if (f->callbacks->down) { 00674 (*f->callbacks->down)(f); /* Inform upper layers */ 00675 } 00676 f->retransmits = 0; 00677 f->state = LS_STOPPING; 00678 TIMEOUT(fsm_timeout, f, f->timeouttime); 00679 break; 00680 } 00681 00682 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 00683 } 00684 00685 00686 /* 00687 * fsm_rtermack - Receive Terminate-Ack. 00688 */ 00689 static void 00690 fsm_rtermack(fsm *f) 00691 { 00692 FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", 00693 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00694 00695 switch (f->state) { 00696 case LS_CLOSING: 00697 UNTIMEOUT(fsm_timeout, f); 00698 f->state = LS_CLOSED; 00699 if( f->callbacks->finished ) { 00700 (*f->callbacks->finished)(f); 00701 } 00702 break; 00703 00704 case LS_STOPPING: 00705 UNTIMEOUT(fsm_timeout, f); 00706 f->state = LS_STOPPED; 00707 if( f->callbacks->finished ) { 00708 (*f->callbacks->finished)(f); 00709 } 00710 break; 00711 00712 case LS_ACKRCVD: 00713 f->state = LS_REQSENT; 00714 break; 00715 00716 case LS_OPENED: 00717 if (f->callbacks->down) { 00718 (*f->callbacks->down)(f); /* Inform upper layers */ 00719 } 00720 fsm_sconfreq(f, 0); 00721 break; 00722 default: 00723 FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", 00724 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00725 } 00726 } 00727 00728 00729 /* 00730 * fsm_rcoderej - Receive an Code-Reject. 00731 */ 00732 static void 00733 fsm_rcoderej(fsm *f, u_char *inp, int len) 00734 { 00735 u_char code, id; 00736 00737 FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", 00738 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00739 00740 if (len < HEADERLEN) { 00741 FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); 00742 return; 00743 } 00744 GETCHAR(code, inp); 00745 GETCHAR(id, inp); 00746 FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", 00747 PROTO_NAME(f), code, id)); 00748 00749 if( f->state == LS_ACKRCVD ) { 00750 f->state = LS_REQSENT; 00751 } 00752 } 00753 00754 00755 /* 00756 * fsm_protreject - Peer doesn't speak this protocol. 00757 * 00758 * Treat this as a catastrophic error (RXJ-). 00759 */ 00760 void 00761 fsm_protreject(fsm *f) 00762 { 00763 switch( f->state ) { 00764 case LS_CLOSING: 00765 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00766 /* fall through */ 00767 case LS_CLOSED: 00768 f->state = LS_CLOSED; 00769 if( f->callbacks->finished ) { 00770 (*f->callbacks->finished)(f); 00771 } 00772 break; 00773 00774 case LS_STOPPING: 00775 case LS_REQSENT: 00776 case LS_ACKRCVD: 00777 case LS_ACKSENT: 00778 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00779 /* fall through */ 00780 case LS_STOPPED: 00781 f->state = LS_STOPPED; 00782 if( f->callbacks->finished ) { 00783 (*f->callbacks->finished)(f); 00784 } 00785 break; 00786 00787 case LS_OPENED: 00788 if( f->callbacks->down ) { 00789 (*f->callbacks->down)(f); 00790 } 00791 /* Init restart counter, send Terminate-Request */ 00792 f->retransmits = f->maxtermtransmits; 00793 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00794 (u_char *) f->term_reason, f->term_reason_len); 00795 TIMEOUT(fsm_timeout, f, f->timeouttime); 00796 --f->retransmits; 00797 00798 f->state = LS_STOPPING; 00799 break; 00800 00801 default: 00802 FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", 00803 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00804 } 00805 } 00806 00807 00808 /* 00809 * fsm_sconfreq - Send a Configure-Request. 00810 */ 00811 static void 00812 fsm_sconfreq(fsm *f, int retransmit) 00813 { 00814 u_char *outp; 00815 int cilen; 00816 00817 if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { 00818 /* Not currently negotiating - reset options */ 00819 if( f->callbacks->resetci ) { 00820 (*f->callbacks->resetci)(f); 00821 } 00822 f->nakloops = 0; 00823 } 00824 00825 if( !retransmit ) { 00826 /* New request - reset retransmission counter, use new ID */ 00827 f->retransmits = f->maxconfreqtransmits; 00828 f->reqid = ++f->id; 00829 } 00830 00831 f->seen_ack = 0; 00832 00833 /* 00834 * Make up the request packet 00835 */ 00836 outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; 00837 if( f->callbacks->cilen && f->callbacks->addci ) { 00838 cilen = (*f->callbacks->cilen)(f); 00839 if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { 00840 cilen = peer_mru[f->unit] - HEADERLEN; 00841 } 00842 if (f->callbacks->addci) { 00843 (*f->callbacks->addci)(f, outp, &cilen); 00844 } 00845 } else { 00846 cilen = 0; 00847 } 00848 00849 /* send the request to our peer */ 00850 fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); 00851 00852 /* start the retransmit timer */ 00853 --f->retransmits; 00854 TIMEOUT(fsm_timeout, f, f->timeouttime); 00855 00856 FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", 00857 PROTO_NAME(f), f->reqid)); 00858 } 00859 00860 00861 /* 00862 * fsm_sdata - Send some data. 00863 * 00864 * Used for all packets sent to our peer by this module. 00865 */ 00866 void 00867 fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) 00868 { 00869 u_char *outp; 00870 int outlen; 00871 00872 /* Adjust length to be smaller than MTU */ 00873 outp = outpacket_buf[f->unit]; 00874 if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { 00875 datalen = peer_mru[f->unit] - HEADERLEN; 00876 } 00877 if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { 00878 BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); 00879 } 00880 outlen = datalen + HEADERLEN; 00881 MAKEHEADER(outp, f->protocol); 00882 PUTCHAR(code, outp); 00883 PUTCHAR(id, outp); 00884 PUTSHORT(outlen, outp); 00885 pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); 00886 FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", 00887 PROTO_NAME(f), code, id, outlen)); 00888 } 00889 00890 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:52:57 by 1.7.2