Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
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 #if PPP_DEBUG 00124 int oldState = f->state; 00125 00126 LWIP_UNUSED_ARG(oldState); 00127 #endif 00128 00129 switch( f->state ) { 00130 case LS_INITIAL: 00131 f->state = LS_CLOSED; 00132 break; 00133 00134 case LS_STARTING: 00135 if( f->flags & OPT_SILENT ) { 00136 f->state = LS_STOPPED; 00137 } else { 00138 /* Send an initial configure-request */ 00139 fsm_sconfreq(f, 0); 00140 f->state = LS_REQSENT; 00141 } 00142 break; 00143 00144 default: 00145 FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", 00146 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00147 } 00148 00149 FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", 00150 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00151 } 00152 00153 00154 /* 00155 * fsm_lowerdown - The lower layer is down. 00156 * 00157 * Cancel all timeouts and inform upper layers. 00158 */ 00159 void 00160 fsm_lowerdown(fsm *f) 00161 { 00162 #if PPP_DEBUG 00163 int oldState = f->state; 00164 00165 LWIP_UNUSED_ARG(oldState); 00166 #endif 00167 00168 switch( f->state ) { 00169 case LS_CLOSED: 00170 f->state = LS_INITIAL; 00171 break; 00172 00173 case LS_STOPPED: 00174 f->state = LS_STARTING; 00175 if( f->callbacks->starting ) { 00176 (*f->callbacks->starting)(f); 00177 } 00178 break; 00179 00180 case LS_CLOSING: 00181 f->state = LS_INITIAL; 00182 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00183 break; 00184 00185 case LS_STOPPING: 00186 case LS_REQSENT: 00187 case LS_ACKRCVD: 00188 case LS_ACKSENT: 00189 f->state = LS_STARTING; 00190 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00191 break; 00192 00193 case LS_OPENED: 00194 if( f->callbacks->down ) { 00195 (*f->callbacks->down)(f); 00196 } 00197 f->state = LS_STARTING; 00198 break; 00199 00200 default: 00201 FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", 00202 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00203 } 00204 00205 FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", 00206 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00207 } 00208 00209 00210 /* 00211 * fsm_open - Link is allowed to come up. 00212 */ 00213 void 00214 fsm_open(fsm *f) 00215 { 00216 #if PPP_DEBUG 00217 int oldState = f->state; 00218 00219 LWIP_UNUSED_ARG(oldState); 00220 #endif 00221 00222 switch( f->state ) { 00223 case LS_INITIAL: 00224 f->state = LS_STARTING; 00225 if( f->callbacks->starting ) { 00226 (*f->callbacks->starting)(f); 00227 } 00228 break; 00229 00230 case LS_CLOSED: 00231 if( f->flags & OPT_SILENT ) { 00232 f->state = LS_STOPPED; 00233 } else { 00234 /* Send an initial configure-request */ 00235 fsm_sconfreq(f, 0); 00236 f->state = LS_REQSENT; 00237 } 00238 break; 00239 00240 case LS_CLOSING: 00241 f->state = LS_STOPPING; 00242 /* fall through */ 00243 case LS_STOPPED: 00244 case LS_OPENED: 00245 if( f->flags & OPT_RESTART ) { 00246 fsm_lowerdown(f); 00247 fsm_lowerup(f); 00248 } 00249 break; 00250 } 00251 00252 FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", 00253 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00254 } 00255 00256 #if 0 /* backport pppd 2.4.4b1; */ 00257 /* 00258 * terminate_layer - Start process of shutting down the FSM 00259 * 00260 * Cancel any timeout running, notify upper layers we're done, and 00261 * send a terminate-request message as configured. 00262 */ 00263 static void 00264 terminate_layer(fsm *f, int nextstate) 00265 { 00266 /* @todo */ 00267 } 00268 #endif 00269 00270 /* 00271 * fsm_close - Start closing connection. 00272 * 00273 * Cancel timeouts and either initiate close or possibly go directly to 00274 * the LS_CLOSED state. 00275 */ 00276 void 00277 fsm_close(fsm *f, char *reason) 00278 { 00279 #if PPP_DEBUG 00280 int oldState = f->state; 00281 00282 LWIP_UNUSED_ARG(oldState); 00283 #endif 00284 00285 f->term_reason = reason; 00286 f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason)); 00287 switch( f->state ) { 00288 case LS_STARTING: 00289 f->state = LS_INITIAL; 00290 break; 00291 case LS_STOPPED: 00292 f->state = LS_CLOSED; 00293 break; 00294 case LS_STOPPING: 00295 f->state = LS_CLOSING; 00296 break; 00297 00298 case LS_REQSENT: 00299 case LS_ACKRCVD: 00300 case LS_ACKSENT: 00301 case LS_OPENED: 00302 if( f->state != LS_OPENED ) { 00303 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00304 } else if( f->callbacks->down ) { 00305 (*f->callbacks->down)(f); /* Inform upper layers we're down */ 00306 } 00307 /* Init restart counter, send Terminate-Request */ 00308 f->retransmits = f->maxtermtransmits; 00309 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00310 (u_char *) f->term_reason, f->term_reason_len); 00311 TIMEOUT(fsm_timeout, f, f->timeouttime); 00312 --f->retransmits; 00313 00314 f->state = LS_CLOSING; 00315 break; 00316 } 00317 00318 FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", 00319 PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 00320 } 00321 00322 00323 /* 00324 * fsm_timeout - Timeout expired. 00325 */ 00326 static void 00327 fsm_timeout(void *arg) 00328 { 00329 fsm *f = (fsm *) arg; 00330 00331 switch (f->state) { 00332 case LS_CLOSING: 00333 case LS_STOPPING: 00334 if( f->retransmits <= 0 ) { 00335 FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", 00336 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00337 /* 00338 * We've waited for an ack long enough. Peer probably heard us. 00339 */ 00340 f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; 00341 if( f->callbacks->finished ) { 00342 (*f->callbacks->finished)(f); 00343 } 00344 } else { 00345 FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", 00346 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00347 /* Send Terminate-Request */ 00348 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00349 (u_char *) f->term_reason, f->term_reason_len); 00350 TIMEOUT(fsm_timeout, f, f->timeouttime); 00351 --f->retransmits; 00352 } 00353 break; 00354 00355 case LS_REQSENT: 00356 case LS_ACKRCVD: 00357 case LS_ACKSENT: 00358 if (f->retransmits <= 0) { 00359 FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", 00360 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00361 f->state = LS_STOPPED; 00362 if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { 00363 (*f->callbacks->finished)(f); 00364 } 00365 } else { 00366 FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", 00367 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00368 /* Retransmit the configure-request */ 00369 if (f->callbacks->retransmit) { 00370 (*f->callbacks->retransmit)(f); 00371 } 00372 fsm_sconfreq(f, 1); /* Re-send Configure-Request */ 00373 if( f->state == LS_ACKRCVD ) { 00374 f->state = LS_REQSENT; 00375 } 00376 } 00377 break; 00378 00379 default: 00380 FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", 00381 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00382 } 00383 } 00384 00385 00386 /* 00387 * fsm_input - Input packet. 00388 */ 00389 void 00390 fsm_input(fsm *f, u_char *inpacket, int l) 00391 { 00392 u_char *inp = inpacket; 00393 u_char code, id; 00394 int len; 00395 00396 /* 00397 * Parse header (code, id and length). 00398 * If packet too short, drop it. 00399 */ 00400 if (l < HEADERLEN) { 00401 FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", 00402 f->protocol)); 00403 return; 00404 } 00405 GETCHAR(code, inp); 00406 GETCHAR(id, inp); 00407 GETSHORT(len, inp); 00408 if (len < HEADERLEN) { 00409 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", 00410 f->protocol)); 00411 return; 00412 } 00413 if (len > l) { 00414 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", 00415 f->protocol)); 00416 return; 00417 } 00418 len -= HEADERLEN; /* subtract header length */ 00419 00420 if( f->state == LS_INITIAL || f->state == LS_STARTING ) { 00421 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", 00422 f->protocol, f->state, ppperr_strerr[f->state])); 00423 return; 00424 } 00425 FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); 00426 /* 00427 * Action depends on code. 00428 */ 00429 switch (code) { 00430 case CONFREQ: 00431 fsm_rconfreq(f, id, inp, len); 00432 break; 00433 00434 case CONFACK: 00435 fsm_rconfack(f, id, inp, len); 00436 break; 00437 00438 case CONFNAK: 00439 case CONFREJ: 00440 fsm_rconfnakrej(f, code, id, inp, len); 00441 break; 00442 00443 case TERMREQ: 00444 fsm_rtermreq(f, id, inp, len); 00445 break; 00446 00447 case TERMACK: 00448 fsm_rtermack(f); 00449 break; 00450 00451 case CODEREJ: 00452 fsm_rcoderej(f, inp, len); 00453 break; 00454 00455 default: 00456 FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); 00457 if( !f->callbacks->extcode || 00458 !(*f->callbacks->extcode)(f, code, id, inp, len) ) { 00459 fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); 00460 } 00461 break; 00462 } 00463 } 00464 00465 00466 /* 00467 * fsm_rconfreq - Receive Configure-Request. 00468 */ 00469 static void 00470 fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) 00471 { 00472 int code, reject_if_disagree; 00473 00474 FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", 00475 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00476 switch( f->state ) { 00477 case LS_CLOSED: 00478 /* Go away, we're closed */ 00479 fsm_sdata(f, TERMACK, id, NULL, 0); 00480 return; 00481 case LS_CLOSING: 00482 case LS_STOPPING: 00483 return; 00484 00485 case LS_OPENED: 00486 /* Go down and restart negotiation */ 00487 if( f->callbacks->down ) { 00488 (*f->callbacks->down)(f); /* Inform upper layers */ 00489 } 00490 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00491 break; 00492 00493 case LS_STOPPED: 00494 /* Negotiation started by our peer */ 00495 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00496 f->state = LS_REQSENT; 00497 break; 00498 } 00499 00500 /* 00501 * Pass the requested configuration options 00502 * to protocol-specific code for checking. 00503 */ 00504 if (f->callbacks->reqci) { /* Check CI */ 00505 reject_if_disagree = (f->nakloops >= f->maxnakloops); 00506 code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); 00507 } else if (len) { 00508 code = CONFREJ; /* Reject all CI */ 00509 } else { 00510 code = CONFACK; 00511 } 00512 00513 /* send the Ack, Nak or Rej to the peer */ 00514 fsm_sdata(f, (u_char)code, id, inp, len); 00515 00516 if (code == CONFACK) { 00517 if (f->state == LS_ACKRCVD) { 00518 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00519 f->state = LS_OPENED; 00520 if (f->callbacks->up) { 00521 (*f->callbacks->up)(f); /* Inform upper layers */ 00522 } 00523 } else { 00524 f->state = LS_ACKSENT; 00525 } 00526 f->nakloops = 0; 00527 } else { 00528 /* we sent CONFACK or CONFREJ */ 00529 if (f->state != LS_ACKRCVD) { 00530 f->state = LS_REQSENT; 00531 } 00532 if( code == CONFNAK ) { 00533 ++f->nakloops; 00534 } 00535 } 00536 } 00537 00538 00539 /* 00540 * fsm_rconfack - Receive Configure-Ack. 00541 */ 00542 static void 00543 fsm_rconfack(fsm *f, int id, u_char *inp, int len) 00544 { 00545 FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", 00546 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00547 00548 if (id != f->reqid || f->seen_ack) { /* Expected id? */ 00549 return; /* Nope, toss... */ 00550 } 00551 if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { 00552 /* Ack is bad - ignore it */ 00553 FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", 00554 PROTO_NAME(f), len)); 00555 return; 00556 } 00557 f->seen_ack = 1; 00558 00559 switch (f->state) { 00560 case LS_CLOSED: 00561 case LS_STOPPED: 00562 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 00563 break; 00564 00565 case LS_REQSENT: 00566 f->state = LS_ACKRCVD; 00567 f->retransmits = f->maxconfreqtransmits; 00568 break; 00569 00570 case LS_ACKRCVD: 00571 /* Huh? an extra valid Ack? oh well... */ 00572 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00573 fsm_sconfreq(f, 0); 00574 f->state = LS_REQSENT; 00575 break; 00576 00577 case LS_ACKSENT: 00578 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00579 f->state = LS_OPENED; 00580 f->retransmits = f->maxconfreqtransmits; 00581 if (f->callbacks->up) { 00582 (*f->callbacks->up)(f); /* Inform upper layers */ 00583 } 00584 break; 00585 00586 case LS_OPENED: 00587 /* Go down and restart negotiation */ 00588 if (f->callbacks->down) { 00589 (*f->callbacks->down)(f); /* Inform upper layers */ 00590 } 00591 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00592 f->state = LS_REQSENT; 00593 break; 00594 } 00595 } 00596 00597 00598 /* 00599 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 00600 */ 00601 static void 00602 fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) 00603 { 00604 int (*proc) (fsm *, u_char *, int); 00605 int ret; 00606 00607 FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", 00608 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00609 00610 if (id != f->reqid || f->seen_ack) { /* Expected id? */ 00611 return; /* Nope, toss... */ 00612 } 00613 proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; 00614 if (!proc || !((ret = proc(f, inp, len)))) { 00615 /* Nak/reject is bad - ignore it */ 00616 FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", 00617 PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); 00618 return; 00619 } 00620 f->seen_ack = 1; 00621 00622 switch (f->state) { 00623 case LS_CLOSED: 00624 case LS_STOPPED: 00625 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 00626 break; 00627 00628 case LS_REQSENT: 00629 case LS_ACKSENT: 00630 /* They didn't agree to what we wanted - try another request */ 00631 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00632 if (ret < 0) { 00633 f->state = LS_STOPPED; /* kludge for stopping CCP */ 00634 } else { 00635 fsm_sconfreq(f, 0); /* Send Configure-Request */ 00636 } 00637 break; 00638 00639 case LS_ACKRCVD: 00640 /* Got a Nak/reject when we had already had an Ack?? oh well... */ 00641 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00642 fsm_sconfreq(f, 0); 00643 f->state = LS_REQSENT; 00644 break; 00645 00646 case LS_OPENED: 00647 /* Go down and restart negotiation */ 00648 if (f->callbacks->down) { 00649 (*f->callbacks->down)(f); /* Inform upper layers */ 00650 } 00651 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00652 f->state = LS_REQSENT; 00653 break; 00654 } 00655 } 00656 00657 00658 /* 00659 * fsm_rtermreq - Receive Terminate-Req. 00660 */ 00661 static void 00662 fsm_rtermreq(fsm *f, int id, u_char *p, int len) 00663 { 00664 LWIP_UNUSED_ARG(p); 00665 00666 FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", 00667 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 00668 00669 switch (f->state) { 00670 case LS_ACKRCVD: 00671 case LS_ACKSENT: 00672 f->state = LS_REQSENT; /* Start over but keep trying */ 00673 break; 00674 00675 case LS_OPENED: 00676 if (len > 0) { 00677 FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); 00678 } else { 00679 FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); 00680 } 00681 if (f->callbacks->down) { 00682 (*f->callbacks->down)(f); /* Inform upper layers */ 00683 } 00684 f->retransmits = 0; 00685 f->state = LS_STOPPING; 00686 TIMEOUT(fsm_timeout, f, f->timeouttime); 00687 break; 00688 } 00689 00690 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 00691 } 00692 00693 00694 /* 00695 * fsm_rtermack - Receive Terminate-Ack. 00696 */ 00697 static void 00698 fsm_rtermack(fsm *f) 00699 { 00700 FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", 00701 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00702 00703 switch (f->state) { 00704 case LS_CLOSING: 00705 UNTIMEOUT(fsm_timeout, f); 00706 f->state = LS_CLOSED; 00707 if( f->callbacks->finished ) { 00708 (*f->callbacks->finished)(f); 00709 } 00710 break; 00711 00712 case LS_STOPPING: 00713 UNTIMEOUT(fsm_timeout, f); 00714 f->state = LS_STOPPED; 00715 if( f->callbacks->finished ) { 00716 (*f->callbacks->finished)(f); 00717 } 00718 break; 00719 00720 case LS_ACKRCVD: 00721 f->state = LS_REQSENT; 00722 break; 00723 00724 case LS_OPENED: 00725 if (f->callbacks->down) { 00726 (*f->callbacks->down)(f); /* Inform upper layers */ 00727 } 00728 fsm_sconfreq(f, 0); 00729 break; 00730 default: 00731 FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", 00732 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00733 } 00734 } 00735 00736 00737 /* 00738 * fsm_rcoderej - Receive an Code-Reject. 00739 */ 00740 static void 00741 fsm_rcoderej(fsm *f, u_char *inp, int len) 00742 { 00743 u_char code, id; 00744 00745 FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", 00746 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00747 00748 if (len < HEADERLEN) { 00749 FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); 00750 return; 00751 } 00752 GETCHAR(code, inp); 00753 GETCHAR(id, inp); 00754 FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", 00755 PROTO_NAME(f), code, id)); 00756 00757 if( f->state == LS_ACKRCVD ) { 00758 f->state = LS_REQSENT; 00759 } 00760 } 00761 00762 00763 /* 00764 * fsm_protreject - Peer doesn't speak this protocol. 00765 * 00766 * Treat this as a catastrophic error (RXJ-). 00767 */ 00768 void 00769 fsm_protreject(fsm *f) 00770 { 00771 switch( f->state ) { 00772 case LS_CLOSING: 00773 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00774 /* fall through */ 00775 case LS_CLOSED: 00776 f->state = LS_CLOSED; 00777 if( f->callbacks->finished ) { 00778 (*f->callbacks->finished)(f); 00779 } 00780 break; 00781 00782 case LS_STOPPING: 00783 case LS_REQSENT: 00784 case LS_ACKRCVD: 00785 case LS_ACKSENT: 00786 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00787 /* fall through */ 00788 case LS_STOPPED: 00789 f->state = LS_STOPPED; 00790 if( f->callbacks->finished ) { 00791 (*f->callbacks->finished)(f); 00792 } 00793 break; 00794 00795 case LS_OPENED: 00796 if( f->callbacks->down ) { 00797 (*f->callbacks->down)(f); 00798 } 00799 /* Init restart counter, send Terminate-Request */ 00800 f->retransmits = f->maxtermtransmits; 00801 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00802 (u_char *) f->term_reason, f->term_reason_len); 00803 TIMEOUT(fsm_timeout, f, f->timeouttime); 00804 --f->retransmits; 00805 00806 f->state = LS_STOPPING; 00807 break; 00808 00809 default: 00810 FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", 00811 PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 00812 } 00813 } 00814 00815 00816 /* 00817 * fsm_sconfreq - Send a Configure-Request. 00818 */ 00819 static void 00820 fsm_sconfreq(fsm *f, int retransmit) 00821 { 00822 u_char *outp; 00823 int cilen; 00824 00825 if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { 00826 /* Not currently negotiating - reset options */ 00827 if( f->callbacks->resetci ) { 00828 (*f->callbacks->resetci)(f); 00829 } 00830 f->nakloops = 0; 00831 } 00832 00833 if( !retransmit ) { 00834 /* New request - reset retransmission counter, use new ID */ 00835 f->retransmits = f->maxconfreqtransmits; 00836 f->reqid = ++f->id; 00837 } 00838 00839 f->seen_ack = 0; 00840 00841 /* 00842 * Make up the request packet 00843 */ 00844 outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; 00845 if( f->callbacks->cilen && f->callbacks->addci ) { 00846 cilen = (*f->callbacks->cilen)(f); 00847 if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { 00848 cilen = peer_mru[f->unit] - HEADERLEN; 00849 } 00850 if (f->callbacks->addci) { 00851 (*f->callbacks->addci)(f, outp, &cilen); 00852 } 00853 } else { 00854 cilen = 0; 00855 } 00856 00857 /* send the request to our peer */ 00858 fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); 00859 00860 /* start the retransmit timer */ 00861 --f->retransmits; 00862 TIMEOUT(fsm_timeout, f, f->timeouttime); 00863 00864 FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", 00865 PROTO_NAME(f), f->reqid)); 00866 } 00867 00868 00869 /* 00870 * fsm_sdata - Send some data. 00871 * 00872 * Used for all packets sent to our peer by this module. 00873 */ 00874 void 00875 fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) 00876 { 00877 u_char *outp; 00878 int outlen; 00879 00880 /* Adjust length to be smaller than MTU */ 00881 outp = outpacket_buf[f->unit]; 00882 if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { 00883 datalen = peer_mru[f->unit] - HEADERLEN; 00884 } 00885 if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { 00886 BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); 00887 } 00888 outlen = datalen + HEADERLEN; 00889 MAKEHEADER(outp, f->protocol); 00890 PUTCHAR(code, outp); 00891 PUTCHAR(id, outp); 00892 PUTSHORT(outlen, outp); 00893 pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); 00894 FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", 00895 PROTO_NAME(f), code, id, outlen)); 00896 } 00897 00898 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 15:37:03 by 1.7.2