Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
lwip_fsm.c
00001 /* 00002 * fsm.c - {Link, IP} Control Protocol Finite State Machine. 00003 * 00004 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * 3. The name "Carnegie Mellon University" must not be used to 00019 * endorse or promote products derived from this software without 00020 * prior written permission. For permission or any legal 00021 * details, please contact 00022 * Office of Technology Transfer 00023 * Carnegie Mellon University 00024 * 5000 Forbes Avenue 00025 * Pittsburgh, PA 15213-3890 00026 * (412) 268-4387, fax: (412) 268-7395 00027 * tech-transfer@andrew.cmu.edu 00028 * 00029 * 4. Redistributions of any form whatsoever must retain the following 00030 * acknowledgment: 00031 * "This product includes software developed by Computing Services 00032 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 00033 * 00034 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 00035 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00036 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 00037 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00038 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 00039 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 00040 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00041 */ 00042 00043 #include "netif/ppp/ppp_opts.h" 00044 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00045 00046 /* 00047 * @todo: 00048 * Randomize fsm id on link/init. 00049 * Deal with variable outgoing MTU. 00050 */ 00051 00052 #if 0 /* UNUSED */ 00053 #include <stdio.h> 00054 #include <string.h> 00055 #include <sys/types.h> 00056 #endif /* UNUSED */ 00057 00058 #include "netif/ppp/ppp_impl.h" 00059 00060 #include "netif/ppp/fsm.h" 00061 00062 static void fsm_timeout (void *); 00063 static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); 00064 static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); 00065 static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); 00066 static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); 00067 static void fsm_rtermack(fsm *f); 00068 static void fsm_rcoderej(fsm *f, u_char *inp, int len); 00069 static void fsm_sconfreq(fsm *f, int retransmit); 00070 00071 #define PROTO_NAME(f) ((f)->callbacks->proto_name) 00072 00073 /* 00074 * fsm_init - Initialize fsm. 00075 * 00076 * Initialize fsm state. 00077 */ 00078 void fsm_init(fsm *f) { 00079 ppp_pcb *pcb = f->pcb; 00080 f->state = PPP_FSM_INITIAL; 00081 f->flags = 0; 00082 f->id = 0; /* XXX Start with random id? */ 00083 f->maxnakloops = pcb->settings.fsm_max_nak_loops; 00084 f->term_reason_len = 0; 00085 } 00086 00087 00088 /* 00089 * fsm_lowerup - The lower layer is up. 00090 */ 00091 void fsm_lowerup(fsm *f) { 00092 switch( f->state ){ 00093 case PPP_FSM_INITIAL: 00094 f->state = PPP_FSM_CLOSED; 00095 break; 00096 00097 case PPP_FSM_STARTING: 00098 if( f->flags & OPT_SILENT ) 00099 f->state = PPP_FSM_STOPPED; 00100 else { 00101 /* Send an initial configure-request */ 00102 fsm_sconfreq(f, 0); 00103 f->state = PPP_FSM_REQSENT; 00104 } 00105 break; 00106 00107 default: 00108 FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); 00109 /* no break */ 00110 } 00111 } 00112 00113 00114 /* 00115 * fsm_lowerdown - The lower layer is down. 00116 * 00117 * Cancel all timeouts and inform upper layers. 00118 */ 00119 void fsm_lowerdown(fsm *f) { 00120 switch( f->state ){ 00121 case PPP_FSM_CLOSED: 00122 f->state = PPP_FSM_INITIAL; 00123 break; 00124 00125 case PPP_FSM_STOPPED: 00126 f->state = PPP_FSM_STARTING; 00127 if( f->callbacks->starting ) 00128 (*f->callbacks->starting)(f); 00129 break; 00130 00131 case PPP_FSM_CLOSING: 00132 f->state = PPP_FSM_INITIAL; 00133 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00134 break; 00135 00136 case PPP_FSM_STOPPING: 00137 case PPP_FSM_REQSENT: 00138 case PPP_FSM_ACKRCVD: 00139 case PPP_FSM_ACKSENT: 00140 f->state = PPP_FSM_STARTING; 00141 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00142 break; 00143 00144 case PPP_FSM_OPENED: 00145 if( f->callbacks->down ) 00146 (*f->callbacks->down)(f); 00147 f->state = PPP_FSM_STARTING; 00148 break; 00149 00150 default: 00151 FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); 00152 /* no break */ 00153 } 00154 } 00155 00156 00157 /* 00158 * fsm_open - Link is allowed to come up. 00159 */ 00160 void fsm_open(fsm *f) { 00161 switch( f->state ){ 00162 case PPP_FSM_INITIAL: 00163 f->state = PPP_FSM_STARTING; 00164 if( f->callbacks->starting ) 00165 (*f->callbacks->starting)(f); 00166 break; 00167 00168 case PPP_FSM_CLOSED: 00169 if( f->flags & OPT_SILENT ) 00170 f->state = PPP_FSM_STOPPED; 00171 else { 00172 /* Send an initial configure-request */ 00173 fsm_sconfreq(f, 0); 00174 f->state = PPP_FSM_REQSENT; 00175 } 00176 break; 00177 00178 case PPP_FSM_CLOSING: 00179 f->state = PPP_FSM_STOPPING; 00180 /* fall through */ 00181 /* no break */ 00182 case PPP_FSM_STOPPED: 00183 case PPP_FSM_OPENED: 00184 if( f->flags & OPT_RESTART ){ 00185 fsm_lowerdown(f); 00186 fsm_lowerup(f); 00187 } 00188 break; 00189 default: 00190 break; 00191 } 00192 } 00193 00194 /* 00195 * terminate_layer - Start process of shutting down the FSM 00196 * 00197 * Cancel any timeout running, notify upper layers we're done, and 00198 * send a terminate-request message as configured. 00199 */ 00200 static void terminate_layer(fsm *f, int nextstate) { 00201 ppp_pcb *pcb = f->pcb; 00202 00203 if( f->state != PPP_FSM_OPENED ) 00204 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00205 else if( f->callbacks->down ) 00206 (*f->callbacks->down)(f); /* Inform upper layers we're down */ 00207 00208 /* Init restart counter and send Terminate-Request */ 00209 f->retransmits = pcb->settings.fsm_max_term_transmits; 00210 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00211 (const u_char *) f->term_reason, f->term_reason_len); 00212 00213 if (f->retransmits == 0) { 00214 /* 00215 * User asked for no terminate requests at all; just close it. 00216 * We've already fired off one Terminate-Request just to be nice 00217 * to the peer, but we're not going to wait for a reply. 00218 */ 00219 f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; 00220 if( f->callbacks->finished ) 00221 (*f->callbacks->finished)(f); 00222 return; 00223 } 00224 00225 TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); 00226 --f->retransmits; 00227 00228 f->state = nextstate; 00229 } 00230 00231 /* 00232 * fsm_close - Start closing connection. 00233 * 00234 * Cancel timeouts and either initiate close or possibly go directly to 00235 * the PPP_FSM_CLOSED state. 00236 */ 00237 void fsm_close(fsm *f, const char *reason) { 00238 f->term_reason = reason; 00239 f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); 00240 switch( f->state ){ 00241 case PPP_FSM_STARTING: 00242 f->state = PPP_FSM_INITIAL; 00243 break; 00244 case PPP_FSM_STOPPED: 00245 f->state = PPP_FSM_CLOSED; 00246 break; 00247 case PPP_FSM_STOPPING: 00248 f->state = PPP_FSM_CLOSING; 00249 break; 00250 00251 case PPP_FSM_REQSENT: 00252 case PPP_FSM_ACKRCVD: 00253 case PPP_FSM_ACKSENT: 00254 case PPP_FSM_OPENED: 00255 terminate_layer(f, PPP_FSM_CLOSING); 00256 break; 00257 default: 00258 break; 00259 } 00260 } 00261 00262 00263 /* 00264 * fsm_timeout - Timeout expired. 00265 */ 00266 static void fsm_timeout(void *arg) { 00267 fsm *f = (fsm *) arg; 00268 ppp_pcb *pcb = f->pcb; 00269 00270 switch (f->state) { 00271 case PPP_FSM_CLOSING: 00272 case PPP_FSM_STOPPING: 00273 if( f->retransmits <= 0 ){ 00274 /* 00275 * We've waited for an ack long enough. Peer probably heard us. 00276 */ 00277 f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; 00278 if( f->callbacks->finished ) 00279 (*f->callbacks->finished)(f); 00280 } else { 00281 /* Send Terminate-Request */ 00282 fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 00283 (const u_char *) f->term_reason, f->term_reason_len); 00284 TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); 00285 --f->retransmits; 00286 } 00287 break; 00288 00289 case PPP_FSM_REQSENT: 00290 case PPP_FSM_ACKRCVD: 00291 case PPP_FSM_ACKSENT: 00292 if (f->retransmits <= 0) { 00293 ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); 00294 f->state = PPP_FSM_STOPPED; 00295 if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) 00296 (*f->callbacks->finished)(f); 00297 00298 } else { 00299 /* Retransmit the configure-request */ 00300 if (f->callbacks->retransmit) 00301 (*f->callbacks->retransmit)(f); 00302 fsm_sconfreq(f, 1); /* Re-send Configure-Request */ 00303 if( f->state == PPP_FSM_ACKRCVD ) 00304 f->state = PPP_FSM_REQSENT; 00305 } 00306 break; 00307 00308 default: 00309 FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); 00310 /* no break */ 00311 } 00312 } 00313 00314 00315 /* 00316 * fsm_input - Input packet. 00317 */ 00318 void fsm_input(fsm *f, u_char *inpacket, int l) { 00319 u_char *inp; 00320 u_char code, id; 00321 int len; 00322 00323 /* 00324 * Parse header (code, id and length). 00325 * If packet too short, drop it. 00326 */ 00327 inp = inpacket; 00328 if (l < HEADERLEN) { 00329 FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); 00330 return; 00331 } 00332 GETCHAR(code, inp); 00333 GETCHAR(id, inp); 00334 GETSHORT(len, inp); 00335 if (len < HEADERLEN) { 00336 FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); 00337 return; 00338 } 00339 if (len > l) { 00340 FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); 00341 return; 00342 } 00343 len -= HEADERLEN; /* subtract header length */ 00344 00345 if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ 00346 FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", 00347 f->protocol, f->state)); 00348 return; 00349 } 00350 00351 /* 00352 * Action depends on code. 00353 */ 00354 switch (code) { 00355 case CONFREQ: 00356 fsm_rconfreq(f, id, inp, len); 00357 break; 00358 00359 case CONFACK: 00360 fsm_rconfack(f, id, inp, len); 00361 break; 00362 00363 case CONFNAK: 00364 case CONFREJ: 00365 fsm_rconfnakrej(f, code, id, inp, len); 00366 break; 00367 00368 case TERMREQ: 00369 fsm_rtermreq(f, id, inp, len); 00370 break; 00371 00372 case TERMACK: 00373 fsm_rtermack(f); 00374 break; 00375 00376 case CODEREJ: 00377 fsm_rcoderej(f, inp, len); 00378 break; 00379 00380 default: 00381 if( !f->callbacks->extcode 00382 || !(*f->callbacks->extcode)(f, code, id, inp, len) ) 00383 fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); 00384 break; 00385 } 00386 } 00387 00388 00389 /* 00390 * fsm_rconfreq - Receive Configure-Request. 00391 */ 00392 static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { 00393 int code, reject_if_disagree; 00394 00395 switch( f->state ){ 00396 case PPP_FSM_CLOSED: 00397 /* Go away, we're closed */ 00398 fsm_sdata(f, TERMACK, id, NULL, 0); 00399 return; 00400 case PPP_FSM_CLOSING: 00401 case PPP_FSM_STOPPING: 00402 return; 00403 00404 case PPP_FSM_OPENED: 00405 /* Go down and restart negotiation */ 00406 if( f->callbacks->down ) 00407 (*f->callbacks->down)(f); /* Inform upper layers */ 00408 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00409 f->state = PPP_FSM_REQSENT; 00410 break; 00411 00412 case PPP_FSM_STOPPED: 00413 /* Negotiation started by our peer */ 00414 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00415 f->state = PPP_FSM_REQSENT; 00416 break; 00417 default: 00418 break; 00419 } 00420 00421 /* 00422 * Pass the requested configuration options 00423 * to protocol-specific code for checking. 00424 */ 00425 if (f->callbacks->reqci){ /* Check CI */ 00426 reject_if_disagree = (f->nakloops >= f->maxnakloops); 00427 code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); 00428 } else if (len) 00429 code = CONFREJ; /* Reject all CI */ 00430 else 00431 code = CONFACK; 00432 00433 /* send the Ack, Nak or Rej to the peer */ 00434 fsm_sdata(f, code, id, inp, len); 00435 00436 if (code == CONFACK) { 00437 if (f->state == PPP_FSM_ACKRCVD) { 00438 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00439 f->state = PPP_FSM_OPENED; 00440 if (f->callbacks->up) 00441 (*f->callbacks->up)(f); /* Inform upper layers */ 00442 } else 00443 f->state = PPP_FSM_ACKSENT; 00444 f->nakloops = 0; 00445 00446 } else { 00447 /* we sent CONFACK or CONFREJ */ 00448 if (f->state != PPP_FSM_ACKRCVD) 00449 f->state = PPP_FSM_REQSENT; 00450 if( code == CONFNAK ) 00451 ++f->nakloops; 00452 } 00453 } 00454 00455 00456 /* 00457 * fsm_rconfack - Receive Configure-Ack. 00458 */ 00459 static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { 00460 ppp_pcb *pcb = f->pcb; 00461 00462 if (id != f->reqid || f->seen_ack) /* Expected id? */ 00463 return; /* Nope, toss... */ 00464 if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): 00465 (len == 0)) ){ 00466 /* Ack is bad - ignore it */ 00467 ppp_error("Received bad configure-ack: %P", inp, len); 00468 return; 00469 } 00470 f->seen_ack = 1; 00471 f->rnakloops = 0; 00472 00473 switch (f->state) { 00474 case PPP_FSM_CLOSED: 00475 case PPP_FSM_STOPPED: 00476 fsm_sdata(f, TERMACK, id, NULL, 0); 00477 break; 00478 00479 case PPP_FSM_REQSENT: 00480 f->state = PPP_FSM_ACKRCVD; 00481 f->retransmits = pcb->settings.fsm_max_conf_req_transmits; 00482 break; 00483 00484 case PPP_FSM_ACKRCVD: 00485 /* Huh? an extra valid Ack? oh well... */ 00486 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00487 fsm_sconfreq(f, 0); 00488 f->state = PPP_FSM_REQSENT; 00489 break; 00490 00491 case PPP_FSM_ACKSENT: 00492 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00493 f->state = PPP_FSM_OPENED; 00494 f->retransmits = pcb->settings.fsm_max_conf_req_transmits; 00495 if (f->callbacks->up) 00496 (*f->callbacks->up)(f); /* Inform upper layers */ 00497 break; 00498 00499 case PPP_FSM_OPENED: 00500 /* Go down and restart negotiation */ 00501 if (f->callbacks->down) 00502 (*f->callbacks->down)(f); /* Inform upper layers */ 00503 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00504 f->state = PPP_FSM_REQSENT; 00505 break; 00506 default: 00507 break; 00508 } 00509 } 00510 00511 00512 /* 00513 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 00514 */ 00515 static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { 00516 int ret; 00517 int treat_as_reject; 00518 00519 if (id != f->reqid || f->seen_ack) /* Expected id? */ 00520 return; /* Nope, toss... */ 00521 00522 if (code == CONFNAK) { 00523 ++f->rnakloops; 00524 treat_as_reject = (f->rnakloops >= f->maxnakloops); 00525 if (f->callbacks->nakci == NULL 00526 || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { 00527 ppp_error("Received bad configure-nak: %P", inp, len); 00528 return; 00529 } 00530 } else { 00531 f->rnakloops = 0; 00532 if (f->callbacks->rejci == NULL 00533 || !(ret = f->callbacks->rejci(f, inp, len))) { 00534 ppp_error("Received bad configure-rej: %P", inp, len); 00535 return; 00536 } 00537 } 00538 00539 f->seen_ack = 1; 00540 00541 switch (f->state) { 00542 case PPP_FSM_CLOSED: 00543 case PPP_FSM_STOPPED: 00544 fsm_sdata(f, TERMACK, id, NULL, 0); 00545 break; 00546 00547 case PPP_FSM_REQSENT: 00548 case PPP_FSM_ACKSENT: 00549 /* They didn't agree to what we wanted - try another request */ 00550 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00551 if (ret < 0) 00552 f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ 00553 else 00554 fsm_sconfreq(f, 0); /* Send Configure-Request */ 00555 break; 00556 00557 case PPP_FSM_ACKRCVD: 00558 /* Got a Nak/reject when we had already had an Ack?? oh well... */ 00559 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00560 fsm_sconfreq(f, 0); 00561 f->state = PPP_FSM_REQSENT; 00562 break; 00563 00564 case PPP_FSM_OPENED: 00565 /* Go down and restart negotiation */ 00566 if (f->callbacks->down) 00567 (*f->callbacks->down)(f); /* Inform upper layers */ 00568 fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 00569 f->state = PPP_FSM_REQSENT; 00570 break; 00571 default: 00572 break; 00573 } 00574 } 00575 00576 00577 /* 00578 * fsm_rtermreq - Receive Terminate-Req. 00579 */ 00580 static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { 00581 ppp_pcb *pcb = f->pcb; 00582 00583 switch (f->state) { 00584 case PPP_FSM_ACKRCVD: 00585 case PPP_FSM_ACKSENT: 00586 f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ 00587 break; 00588 00589 case PPP_FSM_OPENED: 00590 if (len > 0) { 00591 ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); 00592 } else 00593 ppp_info("%s terminated by peer", PROTO_NAME(f)); 00594 f->retransmits = 0; 00595 f->state = PPP_FSM_STOPPING; 00596 if (f->callbacks->down) 00597 (*f->callbacks->down)(f); /* Inform upper layers */ 00598 TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); 00599 break; 00600 default: 00601 break; 00602 } 00603 00604 fsm_sdata(f, TERMACK, id, NULL, 0); 00605 } 00606 00607 00608 /* 00609 * fsm_rtermack - Receive Terminate-Ack. 00610 */ 00611 static void fsm_rtermack(fsm *f) { 00612 switch (f->state) { 00613 case PPP_FSM_CLOSING: 00614 UNTIMEOUT(fsm_timeout, f); 00615 f->state = PPP_FSM_CLOSED; 00616 if( f->callbacks->finished ) 00617 (*f->callbacks->finished)(f); 00618 break; 00619 case PPP_FSM_STOPPING: 00620 UNTIMEOUT(fsm_timeout, f); 00621 f->state = PPP_FSM_STOPPED; 00622 if( f->callbacks->finished ) 00623 (*f->callbacks->finished)(f); 00624 break; 00625 00626 case PPP_FSM_ACKRCVD: 00627 f->state = PPP_FSM_REQSENT; 00628 break; 00629 00630 case PPP_FSM_OPENED: 00631 if (f->callbacks->down) 00632 (*f->callbacks->down)(f); /* Inform upper layers */ 00633 fsm_sconfreq(f, 0); 00634 f->state = PPP_FSM_REQSENT; 00635 break; 00636 default: 00637 break; 00638 } 00639 } 00640 00641 00642 /* 00643 * fsm_rcoderej - Receive an Code-Reject. 00644 */ 00645 static void fsm_rcoderej(fsm *f, u_char *inp, int len) { 00646 u_char code, id; 00647 00648 if (len < HEADERLEN) { 00649 FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); 00650 return; 00651 } 00652 GETCHAR(code, inp); 00653 GETCHAR(id, inp); 00654 ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); 00655 00656 if( f->state == PPP_FSM_ACKRCVD ) 00657 f->state = PPP_FSM_REQSENT; 00658 } 00659 00660 00661 /* 00662 * fsm_protreject - Peer doesn't speak this protocol. 00663 * 00664 * Treat this as a catastrophic error (RXJ-). 00665 */ 00666 void fsm_protreject(fsm *f) { 00667 switch( f->state ){ 00668 case PPP_FSM_CLOSING: 00669 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00670 /* fall through */ 00671 /* no break */ 00672 case PPP_FSM_CLOSED: 00673 f->state = PPP_FSM_CLOSED; 00674 if( f->callbacks->finished ) 00675 (*f->callbacks->finished)(f); 00676 break; 00677 00678 case PPP_FSM_STOPPING: 00679 case PPP_FSM_REQSENT: 00680 case PPP_FSM_ACKRCVD: 00681 case PPP_FSM_ACKSENT: 00682 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 00683 /* fall through */ 00684 /* no break */ 00685 case PPP_FSM_STOPPED: 00686 f->state = PPP_FSM_STOPPED; 00687 if( f->callbacks->finished ) 00688 (*f->callbacks->finished)(f); 00689 break; 00690 00691 case PPP_FSM_OPENED: 00692 terminate_layer(f, PPP_FSM_STOPPING); 00693 break; 00694 00695 default: 00696 FSMDEBUG(("%s: Protocol-reject event in state %d!", 00697 PROTO_NAME(f), f->state)); 00698 /* no break */ 00699 } 00700 } 00701 00702 00703 /* 00704 * fsm_sconfreq - Send a Configure-Request. 00705 */ 00706 static void fsm_sconfreq(fsm *f, int retransmit) { 00707 ppp_pcb *pcb = f->pcb; 00708 struct pbuf *p; 00709 u_char *outp; 00710 int cilen; 00711 00712 if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ 00713 /* Not currently negotiating - reset options */ 00714 if( f->callbacks->resetci ) 00715 (*f->callbacks->resetci)(f); 00716 f->nakloops = 0; 00717 f->rnakloops = 0; 00718 } 00719 00720 if( !retransmit ){ 00721 /* New request - reset retransmission counter, use new ID */ 00722 f->retransmits = pcb->settings.fsm_max_conf_req_transmits; 00723 f->reqid = ++f->id; 00724 } 00725 00726 f->seen_ack = 0; 00727 00728 /* 00729 * Make up the request packet 00730 */ 00731 if( f->callbacks->cilen && f->callbacks->addci ){ 00732 cilen = (*f->callbacks->cilen)(f); 00733 if( cilen > pcb->peer_mru - HEADERLEN ) 00734 cilen = pcb->peer_mru - HEADERLEN; 00735 } else 00736 cilen = 0; 00737 00738 p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); 00739 if(NULL == p) 00740 return; 00741 if(p->tot_len != p->len) { 00742 pbuf_free(p); 00743 return; 00744 } 00745 00746 /* send the request to our peer */ 00747 outp = (u_char*)p->payload; 00748 MAKEHEADER(outp, f->protocol); 00749 PUTCHAR(CONFREQ, outp); 00750 PUTCHAR(f->reqid, outp); 00751 PUTSHORT(cilen + HEADERLEN, outp); 00752 if (cilen != 0) { 00753 (*f->callbacks->addci)(f, outp, &cilen); 00754 LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN); 00755 } 00756 00757 ppp_write(pcb, p); 00758 00759 /* start the retransmit timer */ 00760 --f->retransmits; 00761 TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); 00762 } 00763 00764 00765 /* 00766 * fsm_sdata - Send some data. 00767 * 00768 * Used for all packets sent to our peer by this module. 00769 */ 00770 void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) { 00771 ppp_pcb *pcb = f->pcb; 00772 struct pbuf *p; 00773 u_char *outp; 00774 int outlen; 00775 00776 /* Adjust length to be smaller than MTU */ 00777 if (datalen > pcb->peer_mru - HEADERLEN) 00778 datalen = pcb->peer_mru - HEADERLEN; 00779 outlen = datalen + HEADERLEN; 00780 00781 p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); 00782 if(NULL == p) 00783 return; 00784 if(p->tot_len != p->len) { 00785 pbuf_free(p); 00786 return; 00787 } 00788 00789 outp = (u_char*)p->payload; 00790 if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ 00791 MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); 00792 MAKEHEADER(outp, f->protocol); 00793 PUTCHAR(code, outp); 00794 PUTCHAR(id, outp); 00795 PUTSHORT(outlen, outp); 00796 ppp_write(pcb, p); 00797 } 00798 00799 #endif /* PPP_SUPPORT */
Generated on Fri Jul 22 2022 04:53:52 by
1.7.2
