ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fsm.c
Go to the documentation of this file.
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 Sun May 27 2012 04:36:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.