Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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 Sun Jul 17 2022 08:25:24 by 1.7.2