Committer:
mbed714
Date:
Sat Sep 18 23:05:49 2010 +0000
Revision:
0:d616ece2d859

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed714 0:d616ece2d859 1 /*****************************************************************************
mbed714 0:d616ece2d859 2 * fsm.c - Network Control Protocol Finite State Machine program file.
mbed714 0:d616ece2d859 3 *
mbed714 0:d616ece2d859 4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
mbed714 0:d616ece2d859 5 * portions Copyright (c) 1997 by Global Election Systems Inc.
mbed714 0:d616ece2d859 6 *
mbed714 0:d616ece2d859 7 * The authors hereby grant permission to use, copy, modify, distribute,
mbed714 0:d616ece2d859 8 * and license this software and its documentation for any purpose, provided
mbed714 0:d616ece2d859 9 * that existing copyright notices are retained in all copies and that this
mbed714 0:d616ece2d859 10 * notice and the following disclaimer are included verbatim in any
mbed714 0:d616ece2d859 11 * distributions. No written agreement, license, or royalty fee is required
mbed714 0:d616ece2d859 12 * for any of the authorized uses.
mbed714 0:d616ece2d859 13 *
mbed714 0:d616ece2d859 14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
mbed714 0:d616ece2d859 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
mbed714 0:d616ece2d859 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
mbed714 0:d616ece2d859 17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
mbed714 0:d616ece2d859 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
mbed714 0:d616ece2d859 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
mbed714 0:d616ece2d859 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
mbed714 0:d616ece2d859 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
mbed714 0:d616ece2d859 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
mbed714 0:d616ece2d859 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mbed714 0:d616ece2d859 24 *
mbed714 0:d616ece2d859 25 ******************************************************************************
mbed714 0:d616ece2d859 26 * REVISION HISTORY
mbed714 0:d616ece2d859 27 *
mbed714 0:d616ece2d859 28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
mbed714 0:d616ece2d859 29 * Ported to lwIP.
mbed714 0:d616ece2d859 30 * 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
mbed714 0:d616ece2d859 31 * Original based on BSD fsm.c.
mbed714 0:d616ece2d859 32 *****************************************************************************/
mbed714 0:d616ece2d859 33 /*
mbed714 0:d616ece2d859 34 * fsm.c - {Link, IP} Control Protocol Finite State Machine.
mbed714 0:d616ece2d859 35 *
mbed714 0:d616ece2d859 36 * Copyright (c) 1989 Carnegie Mellon University.
mbed714 0:d616ece2d859 37 * All rights reserved.
mbed714 0:d616ece2d859 38 *
mbed714 0:d616ece2d859 39 * Redistribution and use in source and binary forms are permitted
mbed714 0:d616ece2d859 40 * provided that the above copyright notice and this paragraph are
mbed714 0:d616ece2d859 41 * duplicated in all such forms and that any documentation,
mbed714 0:d616ece2d859 42 * advertising materials, and other materials related to such
mbed714 0:d616ece2d859 43 * distribution and use acknowledge that the software was developed
mbed714 0:d616ece2d859 44 * by Carnegie Mellon University. The name of the
mbed714 0:d616ece2d859 45 * University may not be used to endorse or promote products derived
mbed714 0:d616ece2d859 46 * from this software without specific prior written permission.
mbed714 0:d616ece2d859 47 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
mbed714 0:d616ece2d859 48 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
mbed714 0:d616ece2d859 49 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
mbed714 0:d616ece2d859 50 */
mbed714 0:d616ece2d859 51
mbed714 0:d616ece2d859 52 /*
mbed714 0:d616ece2d859 53 * TODO:
mbed714 0:d616ece2d859 54 * Randomize fsm id on link/init.
mbed714 0:d616ece2d859 55 * Deal with variable outgoing MTU.
mbed714 0:d616ece2d859 56 */
mbed714 0:d616ece2d859 57
mbed714 0:d616ece2d859 58 #include "lwip/opt.h"
mbed714 0:d616ece2d859 59
mbed714 0:d616ece2d859 60 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
mbed714 0:d616ece2d859 61
mbed714 0:d616ece2d859 62 #include "ppp.h"
mbed714 0:d616ece2d859 63 #include "pppdebug.h"
mbed714 0:d616ece2d859 64
mbed714 0:d616ece2d859 65 #include "fsm.h"
mbed714 0:d616ece2d859 66
mbed714 0:d616ece2d859 67 #include <string.h>
mbed714 0:d616ece2d859 68
mbed714 0:d616ece2d859 69 #if PPP_DEBUG
mbed714 0:d616ece2d859 70 static const char *ppperr_strerr[] = {
mbed714 0:d616ece2d859 71 "LS_INITIAL", /* LS_INITIAL 0 */
mbed714 0:d616ece2d859 72 "LS_STARTING", /* LS_STARTING 1 */
mbed714 0:d616ece2d859 73 "LS_CLOSED", /* LS_CLOSED 2 */
mbed714 0:d616ece2d859 74 "LS_STOPPED", /* LS_STOPPED 3 */
mbed714 0:d616ece2d859 75 "LS_CLOSING", /* LS_CLOSING 4 */
mbed714 0:d616ece2d859 76 "LS_STOPPING", /* LS_STOPPING 5 */
mbed714 0:d616ece2d859 77 "LS_REQSENT", /* LS_REQSENT 6 */
mbed714 0:d616ece2d859 78 "LS_ACKRCVD", /* LS_ACKRCVD 7 */
mbed714 0:d616ece2d859 79 "LS_ACKSENT", /* LS_ACKSENT 8 */
mbed714 0:d616ece2d859 80 "LS_OPENED" /* LS_OPENED 9 */
mbed714 0:d616ece2d859 81 };
mbed714 0:d616ece2d859 82 #endif /* PPP_DEBUG */
mbed714 0:d616ece2d859 83
mbed714 0:d616ece2d859 84 static void fsm_timeout (void *);
mbed714 0:d616ece2d859 85 static void fsm_rconfreq (fsm *, u_char, u_char *, int);
mbed714 0:d616ece2d859 86 static void fsm_rconfack (fsm *, int, u_char *, int);
mbed714 0:d616ece2d859 87 static void fsm_rconfnakrej (fsm *, int, int, u_char *, int);
mbed714 0:d616ece2d859 88 static void fsm_rtermreq (fsm *, int, u_char *, int);
mbed714 0:d616ece2d859 89 static void fsm_rtermack (fsm *);
mbed714 0:d616ece2d859 90 static void fsm_rcoderej (fsm *, u_char *, int);
mbed714 0:d616ece2d859 91 static void fsm_sconfreq (fsm *, int);
mbed714 0:d616ece2d859 92
mbed714 0:d616ece2d859 93 #define PROTO_NAME(f) ((f)->callbacks->proto_name)
mbed714 0:d616ece2d859 94
mbed714 0:d616ece2d859 95 int peer_mru[NUM_PPP];
mbed714 0:d616ece2d859 96
mbed714 0:d616ece2d859 97
mbed714 0:d616ece2d859 98 /*
mbed714 0:d616ece2d859 99 * fsm_init - Initialize fsm.
mbed714 0:d616ece2d859 100 *
mbed714 0:d616ece2d859 101 * Initialize fsm state.
mbed714 0:d616ece2d859 102 */
mbed714 0:d616ece2d859 103 void
mbed714 0:d616ece2d859 104 fsm_init(fsm *f)
mbed714 0:d616ece2d859 105 {
mbed714 0:d616ece2d859 106 f->state = LS_INITIAL;
mbed714 0:d616ece2d859 107 f->flags = 0;
mbed714 0:d616ece2d859 108 f->id = 0; /* XXX Start with random id? */
mbed714 0:d616ece2d859 109 f->timeouttime = FSM_DEFTIMEOUT;
mbed714 0:d616ece2d859 110 f->maxconfreqtransmits = FSM_DEFMAXCONFREQS;
mbed714 0:d616ece2d859 111 f->maxtermtransmits = FSM_DEFMAXTERMREQS;
mbed714 0:d616ece2d859 112 f->maxnakloops = FSM_DEFMAXNAKLOOPS;
mbed714 0:d616ece2d859 113 f->term_reason_len = 0;
mbed714 0:d616ece2d859 114 }
mbed714 0:d616ece2d859 115
mbed714 0:d616ece2d859 116
mbed714 0:d616ece2d859 117 /*
mbed714 0:d616ece2d859 118 * fsm_lowerup - The lower layer is up.
mbed714 0:d616ece2d859 119 */
mbed714 0:d616ece2d859 120 void
mbed714 0:d616ece2d859 121 fsm_lowerup(fsm *f)
mbed714 0:d616ece2d859 122 {
mbed714 0:d616ece2d859 123 int oldState = f->state;
mbed714 0:d616ece2d859 124
mbed714 0:d616ece2d859 125 LWIP_UNUSED_ARG(oldState);
mbed714 0:d616ece2d859 126
mbed714 0:d616ece2d859 127 switch( f->state ) {
mbed714 0:d616ece2d859 128 case LS_INITIAL:
mbed714 0:d616ece2d859 129 f->state = LS_CLOSED;
mbed714 0:d616ece2d859 130 break;
mbed714 0:d616ece2d859 131
mbed714 0:d616ece2d859 132 case LS_STARTING:
mbed714 0:d616ece2d859 133 if( f->flags & OPT_SILENT ) {
mbed714 0:d616ece2d859 134 f->state = LS_STOPPED;
mbed714 0:d616ece2d859 135 } else {
mbed714 0:d616ece2d859 136 /* Send an initial configure-request */
mbed714 0:d616ece2d859 137 fsm_sconfreq(f, 0);
mbed714 0:d616ece2d859 138 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 139 }
mbed714 0:d616ece2d859 140 break;
mbed714 0:d616ece2d859 141
mbed714 0:d616ece2d859 142 default:
mbed714 0:d616ece2d859 143 FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n",
mbed714 0:d616ece2d859 144 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 145 }
mbed714 0:d616ece2d859 146
mbed714 0:d616ece2d859 147 FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n",
mbed714 0:d616ece2d859 148 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 149 }
mbed714 0:d616ece2d859 150
mbed714 0:d616ece2d859 151
mbed714 0:d616ece2d859 152 /*
mbed714 0:d616ece2d859 153 * fsm_lowerdown - The lower layer is down.
mbed714 0:d616ece2d859 154 *
mbed714 0:d616ece2d859 155 * Cancel all timeouts and inform upper layers.
mbed714 0:d616ece2d859 156 */
mbed714 0:d616ece2d859 157 void
mbed714 0:d616ece2d859 158 fsm_lowerdown(fsm *f)
mbed714 0:d616ece2d859 159 {
mbed714 0:d616ece2d859 160 int oldState = f->state;
mbed714 0:d616ece2d859 161
mbed714 0:d616ece2d859 162 LWIP_UNUSED_ARG(oldState);
mbed714 0:d616ece2d859 163
mbed714 0:d616ece2d859 164 switch( f->state ) {
mbed714 0:d616ece2d859 165 case LS_CLOSED:
mbed714 0:d616ece2d859 166 f->state = LS_INITIAL;
mbed714 0:d616ece2d859 167 break;
mbed714 0:d616ece2d859 168
mbed714 0:d616ece2d859 169 case LS_STOPPED:
mbed714 0:d616ece2d859 170 f->state = LS_STARTING;
mbed714 0:d616ece2d859 171 if( f->callbacks->starting ) {
mbed714 0:d616ece2d859 172 (*f->callbacks->starting)(f);
mbed714 0:d616ece2d859 173 }
mbed714 0:d616ece2d859 174 break;
mbed714 0:d616ece2d859 175
mbed714 0:d616ece2d859 176 case LS_CLOSING:
mbed714 0:d616ece2d859 177 f->state = LS_INITIAL;
mbed714 0:d616ece2d859 178 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 179 break;
mbed714 0:d616ece2d859 180
mbed714 0:d616ece2d859 181 case LS_STOPPING:
mbed714 0:d616ece2d859 182 case LS_REQSENT:
mbed714 0:d616ece2d859 183 case LS_ACKRCVD:
mbed714 0:d616ece2d859 184 case LS_ACKSENT:
mbed714 0:d616ece2d859 185 f->state = LS_STARTING;
mbed714 0:d616ece2d859 186 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 187 break;
mbed714 0:d616ece2d859 188
mbed714 0:d616ece2d859 189 case LS_OPENED:
mbed714 0:d616ece2d859 190 if( f->callbacks->down ) {
mbed714 0:d616ece2d859 191 (*f->callbacks->down)(f);
mbed714 0:d616ece2d859 192 }
mbed714 0:d616ece2d859 193 f->state = LS_STARTING;
mbed714 0:d616ece2d859 194 break;
mbed714 0:d616ece2d859 195
mbed714 0:d616ece2d859 196 default:
mbed714 0:d616ece2d859 197 FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n",
mbed714 0:d616ece2d859 198 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 199 }
mbed714 0:d616ece2d859 200
mbed714 0:d616ece2d859 201 FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n",
mbed714 0:d616ece2d859 202 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 203 }
mbed714 0:d616ece2d859 204
mbed714 0:d616ece2d859 205
mbed714 0:d616ece2d859 206 /*
mbed714 0:d616ece2d859 207 * fsm_open - Link is allowed to come up.
mbed714 0:d616ece2d859 208 */
mbed714 0:d616ece2d859 209 void
mbed714 0:d616ece2d859 210 fsm_open(fsm *f)
mbed714 0:d616ece2d859 211 {
mbed714 0:d616ece2d859 212 int oldState = f->state;
mbed714 0:d616ece2d859 213
mbed714 0:d616ece2d859 214 LWIP_UNUSED_ARG(oldState);
mbed714 0:d616ece2d859 215
mbed714 0:d616ece2d859 216 switch( f->state ) {
mbed714 0:d616ece2d859 217 case LS_INITIAL:
mbed714 0:d616ece2d859 218 f->state = LS_STARTING;
mbed714 0:d616ece2d859 219 if( f->callbacks->starting ) {
mbed714 0:d616ece2d859 220 (*f->callbacks->starting)(f);
mbed714 0:d616ece2d859 221 }
mbed714 0:d616ece2d859 222 break;
mbed714 0:d616ece2d859 223
mbed714 0:d616ece2d859 224 case LS_CLOSED:
mbed714 0:d616ece2d859 225 if( f->flags & OPT_SILENT ) {
mbed714 0:d616ece2d859 226 f->state = LS_STOPPED;
mbed714 0:d616ece2d859 227 } else {
mbed714 0:d616ece2d859 228 /* Send an initial configure-request */
mbed714 0:d616ece2d859 229 fsm_sconfreq(f, 0);
mbed714 0:d616ece2d859 230 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 231 }
mbed714 0:d616ece2d859 232 break;
mbed714 0:d616ece2d859 233
mbed714 0:d616ece2d859 234 case LS_CLOSING:
mbed714 0:d616ece2d859 235 f->state = LS_STOPPING;
mbed714 0:d616ece2d859 236 /* fall through */
mbed714 0:d616ece2d859 237 case LS_STOPPED:
mbed714 0:d616ece2d859 238 case LS_OPENED:
mbed714 0:d616ece2d859 239 if( f->flags & OPT_RESTART ) {
mbed714 0:d616ece2d859 240 fsm_lowerdown(f);
mbed714 0:d616ece2d859 241 fsm_lowerup(f);
mbed714 0:d616ece2d859 242 }
mbed714 0:d616ece2d859 243 break;
mbed714 0:d616ece2d859 244 }
mbed714 0:d616ece2d859 245
mbed714 0:d616ece2d859 246 FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n",
mbed714 0:d616ece2d859 247 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 248 }
mbed714 0:d616ece2d859 249
mbed714 0:d616ece2d859 250 #if 0 /* backport pppd 2.4.4b1; */
mbed714 0:d616ece2d859 251 /*
mbed714 0:d616ece2d859 252 * terminate_layer - Start process of shutting down the FSM
mbed714 0:d616ece2d859 253 *
mbed714 0:d616ece2d859 254 * Cancel any timeout running, notify upper layers we're done, and
mbed714 0:d616ece2d859 255 * send a terminate-request message as configured.
mbed714 0:d616ece2d859 256 */
mbed714 0:d616ece2d859 257 static void
mbed714 0:d616ece2d859 258 terminate_layer(fsm *f, int nextstate)
mbed714 0:d616ece2d859 259 {
mbed714 0:d616ece2d859 260 /* @todo */
mbed714 0:d616ece2d859 261 }
mbed714 0:d616ece2d859 262 #endif
mbed714 0:d616ece2d859 263
mbed714 0:d616ece2d859 264 /*
mbed714 0:d616ece2d859 265 * fsm_close - Start closing connection.
mbed714 0:d616ece2d859 266 *
mbed714 0:d616ece2d859 267 * Cancel timeouts and either initiate close or possibly go directly to
mbed714 0:d616ece2d859 268 * the LS_CLOSED state.
mbed714 0:d616ece2d859 269 */
mbed714 0:d616ece2d859 270 void
mbed714 0:d616ece2d859 271 fsm_close(fsm *f, char *reason)
mbed714 0:d616ece2d859 272 {
mbed714 0:d616ece2d859 273 int oldState = f->state;
mbed714 0:d616ece2d859 274
mbed714 0:d616ece2d859 275 LWIP_UNUSED_ARG(oldState);
mbed714 0:d616ece2d859 276
mbed714 0:d616ece2d859 277 f->term_reason = reason;
mbed714 0:d616ece2d859 278 f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason));
mbed714 0:d616ece2d859 279 switch( f->state ) {
mbed714 0:d616ece2d859 280 case LS_STARTING:
mbed714 0:d616ece2d859 281 f->state = LS_INITIAL;
mbed714 0:d616ece2d859 282 break;
mbed714 0:d616ece2d859 283 case LS_STOPPED:
mbed714 0:d616ece2d859 284 f->state = LS_CLOSED;
mbed714 0:d616ece2d859 285 break;
mbed714 0:d616ece2d859 286 case LS_STOPPING:
mbed714 0:d616ece2d859 287 f->state = LS_CLOSING;
mbed714 0:d616ece2d859 288 break;
mbed714 0:d616ece2d859 289
mbed714 0:d616ece2d859 290 case LS_REQSENT:
mbed714 0:d616ece2d859 291 case LS_ACKRCVD:
mbed714 0:d616ece2d859 292 case LS_ACKSENT:
mbed714 0:d616ece2d859 293 case LS_OPENED:
mbed714 0:d616ece2d859 294 if( f->state != LS_OPENED ) {
mbed714 0:d616ece2d859 295 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 296 } else if( f->callbacks->down ) {
mbed714 0:d616ece2d859 297 (*f->callbacks->down)(f); /* Inform upper layers we're down */
mbed714 0:d616ece2d859 298 }
mbed714 0:d616ece2d859 299 /* Init restart counter, send Terminate-Request */
mbed714 0:d616ece2d859 300 f->retransmits = f->maxtermtransmits;
mbed714 0:d616ece2d859 301 fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
mbed714 0:d616ece2d859 302 (u_char *) f->term_reason, f->term_reason_len);
mbed714 0:d616ece2d859 303 TIMEOUT(fsm_timeout, f, f->timeouttime);
mbed714 0:d616ece2d859 304 --f->retransmits;
mbed714 0:d616ece2d859 305
mbed714 0:d616ece2d859 306 f->state = LS_CLOSING;
mbed714 0:d616ece2d859 307 break;
mbed714 0:d616ece2d859 308 }
mbed714 0:d616ece2d859 309
mbed714 0:d616ece2d859 310 FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n",
mbed714 0:d616ece2d859 311 PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 312 }
mbed714 0:d616ece2d859 313
mbed714 0:d616ece2d859 314
mbed714 0:d616ece2d859 315 /*
mbed714 0:d616ece2d859 316 * fsm_timeout - Timeout expired.
mbed714 0:d616ece2d859 317 */
mbed714 0:d616ece2d859 318 static void
mbed714 0:d616ece2d859 319 fsm_timeout(void *arg)
mbed714 0:d616ece2d859 320 {
mbed714 0:d616ece2d859 321 fsm *f = (fsm *) arg;
mbed714 0:d616ece2d859 322
mbed714 0:d616ece2d859 323 switch (f->state) {
mbed714 0:d616ece2d859 324 case LS_CLOSING:
mbed714 0:d616ece2d859 325 case LS_STOPPING:
mbed714 0:d616ece2d859 326 if( f->retransmits <= 0 ) {
mbed714 0:d616ece2d859 327 FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n",
mbed714 0:d616ece2d859 328 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 329 /*
mbed714 0:d616ece2d859 330 * We've waited for an ack long enough. Peer probably heard us.
mbed714 0:d616ece2d859 331 */
mbed714 0:d616ece2d859 332 f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
mbed714 0:d616ece2d859 333 if( f->callbacks->finished ) {
mbed714 0:d616ece2d859 334 (*f->callbacks->finished)(f);
mbed714 0:d616ece2d859 335 }
mbed714 0:d616ece2d859 336 } else {
mbed714 0:d616ece2d859 337 FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n",
mbed714 0:d616ece2d859 338 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 339 /* Send Terminate-Request */
mbed714 0:d616ece2d859 340 fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
mbed714 0:d616ece2d859 341 (u_char *) f->term_reason, f->term_reason_len);
mbed714 0:d616ece2d859 342 TIMEOUT(fsm_timeout, f, f->timeouttime);
mbed714 0:d616ece2d859 343 --f->retransmits;
mbed714 0:d616ece2d859 344 }
mbed714 0:d616ece2d859 345 break;
mbed714 0:d616ece2d859 346
mbed714 0:d616ece2d859 347 case LS_REQSENT:
mbed714 0:d616ece2d859 348 case LS_ACKRCVD:
mbed714 0:d616ece2d859 349 case LS_ACKSENT:
mbed714 0:d616ece2d859 350 if (f->retransmits <= 0) {
mbed714 0:d616ece2d859 351 FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n",
mbed714 0:d616ece2d859 352 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 353 f->state = LS_STOPPED;
mbed714 0:d616ece2d859 354 if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
mbed714 0:d616ece2d859 355 (*f->callbacks->finished)(f);
mbed714 0:d616ece2d859 356 }
mbed714 0:d616ece2d859 357 } else {
mbed714 0:d616ece2d859 358 FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n",
mbed714 0:d616ece2d859 359 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 360 /* Retransmit the configure-request */
mbed714 0:d616ece2d859 361 if (f->callbacks->retransmit) {
mbed714 0:d616ece2d859 362 (*f->callbacks->retransmit)(f);
mbed714 0:d616ece2d859 363 }
mbed714 0:d616ece2d859 364 fsm_sconfreq(f, 1); /* Re-send Configure-Request */
mbed714 0:d616ece2d859 365 if( f->state == LS_ACKRCVD ) {
mbed714 0:d616ece2d859 366 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 367 }
mbed714 0:d616ece2d859 368 }
mbed714 0:d616ece2d859 369 break;
mbed714 0:d616ece2d859 370
mbed714 0:d616ece2d859 371 default:
mbed714 0:d616ece2d859 372 FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n",
mbed714 0:d616ece2d859 373 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 374 }
mbed714 0:d616ece2d859 375 }
mbed714 0:d616ece2d859 376
mbed714 0:d616ece2d859 377
mbed714 0:d616ece2d859 378 /*
mbed714 0:d616ece2d859 379 * fsm_input - Input packet.
mbed714 0:d616ece2d859 380 */
mbed714 0:d616ece2d859 381 void
mbed714 0:d616ece2d859 382 fsm_input(fsm *f, u_char *inpacket, int l)
mbed714 0:d616ece2d859 383 {
mbed714 0:d616ece2d859 384 u_char *inp = inpacket;
mbed714 0:d616ece2d859 385 u_char code, id;
mbed714 0:d616ece2d859 386 int len;
mbed714 0:d616ece2d859 387
mbed714 0:d616ece2d859 388 /*
mbed714 0:d616ece2d859 389 * Parse header (code, id and length).
mbed714 0:d616ece2d859 390 * If packet too short, drop it.
mbed714 0:d616ece2d859 391 */
mbed714 0:d616ece2d859 392 if (l < HEADERLEN) {
mbed714 0:d616ece2d859 393 FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n",
mbed714 0:d616ece2d859 394 f->protocol));
mbed714 0:d616ece2d859 395 return;
mbed714 0:d616ece2d859 396 }
mbed714 0:d616ece2d859 397 GETCHAR(code, inp);
mbed714 0:d616ece2d859 398 GETCHAR(id, inp);
mbed714 0:d616ece2d859 399 GETSHORT(len, inp);
mbed714 0:d616ece2d859 400 if (len < HEADERLEN) {
mbed714 0:d616ece2d859 401 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n",
mbed714 0:d616ece2d859 402 f->protocol));
mbed714 0:d616ece2d859 403 return;
mbed714 0:d616ece2d859 404 }
mbed714 0:d616ece2d859 405 if (len > l) {
mbed714 0:d616ece2d859 406 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n",
mbed714 0:d616ece2d859 407 f->protocol));
mbed714 0:d616ece2d859 408 return;
mbed714 0:d616ece2d859 409 }
mbed714 0:d616ece2d859 410 len -= HEADERLEN; /* subtract header length */
mbed714 0:d616ece2d859 411
mbed714 0:d616ece2d859 412 if( f->state == LS_INITIAL || f->state == LS_STARTING ) {
mbed714 0:d616ece2d859 413 FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n",
mbed714 0:d616ece2d859 414 f->protocol, f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 415 return;
mbed714 0:d616ece2d859 416 }
mbed714 0:d616ece2d859 417 FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
mbed714 0:d616ece2d859 418 /*
mbed714 0:d616ece2d859 419 * Action depends on code.
mbed714 0:d616ece2d859 420 */
mbed714 0:d616ece2d859 421 switch (code) {
mbed714 0:d616ece2d859 422 case CONFREQ:
mbed714 0:d616ece2d859 423 fsm_rconfreq(f, id, inp, len);
mbed714 0:d616ece2d859 424 break;
mbed714 0:d616ece2d859 425
mbed714 0:d616ece2d859 426 case CONFACK:
mbed714 0:d616ece2d859 427 fsm_rconfack(f, id, inp, len);
mbed714 0:d616ece2d859 428 break;
mbed714 0:d616ece2d859 429
mbed714 0:d616ece2d859 430 case CONFNAK:
mbed714 0:d616ece2d859 431 case CONFREJ:
mbed714 0:d616ece2d859 432 fsm_rconfnakrej(f, code, id, inp, len);
mbed714 0:d616ece2d859 433 break;
mbed714 0:d616ece2d859 434
mbed714 0:d616ece2d859 435 case TERMREQ:
mbed714 0:d616ece2d859 436 fsm_rtermreq(f, id, inp, len);
mbed714 0:d616ece2d859 437 break;
mbed714 0:d616ece2d859 438
mbed714 0:d616ece2d859 439 case TERMACK:
mbed714 0:d616ece2d859 440 fsm_rtermack(f);
mbed714 0:d616ece2d859 441 break;
mbed714 0:d616ece2d859 442
mbed714 0:d616ece2d859 443 case CODEREJ:
mbed714 0:d616ece2d859 444 fsm_rcoderej(f, inp, len);
mbed714 0:d616ece2d859 445 break;
mbed714 0:d616ece2d859 446
mbed714 0:d616ece2d859 447 default:
mbed714 0:d616ece2d859 448 FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f)));
mbed714 0:d616ece2d859 449 if( !f->callbacks->extcode ||
mbed714 0:d616ece2d859 450 !(*f->callbacks->extcode)(f, code, id, inp, len) ) {
mbed714 0:d616ece2d859 451 fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
mbed714 0:d616ece2d859 452 }
mbed714 0:d616ece2d859 453 break;
mbed714 0:d616ece2d859 454 }
mbed714 0:d616ece2d859 455 }
mbed714 0:d616ece2d859 456
mbed714 0:d616ece2d859 457
mbed714 0:d616ece2d859 458 /*
mbed714 0:d616ece2d859 459 * fsm_rconfreq - Receive Configure-Request.
mbed714 0:d616ece2d859 460 */
mbed714 0:d616ece2d859 461 static void
mbed714 0:d616ece2d859 462 fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
mbed714 0:d616ece2d859 463 {
mbed714 0:d616ece2d859 464 int code, reject_if_disagree;
mbed714 0:d616ece2d859 465
mbed714 0:d616ece2d859 466 FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
mbed714 0:d616ece2d859 467 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 468 switch( f->state ) {
mbed714 0:d616ece2d859 469 case LS_CLOSED:
mbed714 0:d616ece2d859 470 /* Go away, we're closed */
mbed714 0:d616ece2d859 471 fsm_sdata(f, TERMACK, id, NULL, 0);
mbed714 0:d616ece2d859 472 return;
mbed714 0:d616ece2d859 473 case LS_CLOSING:
mbed714 0:d616ece2d859 474 case LS_STOPPING:
mbed714 0:d616ece2d859 475 return;
mbed714 0:d616ece2d859 476
mbed714 0:d616ece2d859 477 case LS_OPENED:
mbed714 0:d616ece2d859 478 /* Go down and restart negotiation */
mbed714 0:d616ece2d859 479 if( f->callbacks->down ) {
mbed714 0:d616ece2d859 480 (*f->callbacks->down)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 481 }
mbed714 0:d616ece2d859 482 fsm_sconfreq(f, 0); /* Send initial Configure-Request */
mbed714 0:d616ece2d859 483 break;
mbed714 0:d616ece2d859 484
mbed714 0:d616ece2d859 485 case LS_STOPPED:
mbed714 0:d616ece2d859 486 /* Negotiation started by our peer */
mbed714 0:d616ece2d859 487 fsm_sconfreq(f, 0); /* Send initial Configure-Request */
mbed714 0:d616ece2d859 488 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 489 break;
mbed714 0:d616ece2d859 490 }
mbed714 0:d616ece2d859 491
mbed714 0:d616ece2d859 492 /*
mbed714 0:d616ece2d859 493 * Pass the requested configuration options
mbed714 0:d616ece2d859 494 * to protocol-specific code for checking.
mbed714 0:d616ece2d859 495 */
mbed714 0:d616ece2d859 496 if (f->callbacks->reqci) { /* Check CI */
mbed714 0:d616ece2d859 497 reject_if_disagree = (f->nakloops >= f->maxnakloops);
mbed714 0:d616ece2d859 498 code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
mbed714 0:d616ece2d859 499 } else if (len) {
mbed714 0:d616ece2d859 500 code = CONFREJ; /* Reject all CI */
mbed714 0:d616ece2d859 501 } else {
mbed714 0:d616ece2d859 502 code = CONFACK;
mbed714 0:d616ece2d859 503 }
mbed714 0:d616ece2d859 504
mbed714 0:d616ece2d859 505 /* send the Ack, Nak or Rej to the peer */
mbed714 0:d616ece2d859 506 fsm_sdata(f, (u_char)code, id, inp, len);
mbed714 0:d616ece2d859 507
mbed714 0:d616ece2d859 508 if (code == CONFACK) {
mbed714 0:d616ece2d859 509 if (f->state == LS_ACKRCVD) {
mbed714 0:d616ece2d859 510 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 511 f->state = LS_OPENED;
mbed714 0:d616ece2d859 512 if (f->callbacks->up) {
mbed714 0:d616ece2d859 513 (*f->callbacks->up)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 514 }
mbed714 0:d616ece2d859 515 } else {
mbed714 0:d616ece2d859 516 f->state = LS_ACKSENT;
mbed714 0:d616ece2d859 517 }
mbed714 0:d616ece2d859 518 f->nakloops = 0;
mbed714 0:d616ece2d859 519 } else {
mbed714 0:d616ece2d859 520 /* we sent CONFACK or CONFREJ */
mbed714 0:d616ece2d859 521 if (f->state != LS_ACKRCVD) {
mbed714 0:d616ece2d859 522 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 523 }
mbed714 0:d616ece2d859 524 if( code == CONFNAK ) {
mbed714 0:d616ece2d859 525 ++f->nakloops;
mbed714 0:d616ece2d859 526 }
mbed714 0:d616ece2d859 527 }
mbed714 0:d616ece2d859 528 }
mbed714 0:d616ece2d859 529
mbed714 0:d616ece2d859 530
mbed714 0:d616ece2d859 531 /*
mbed714 0:d616ece2d859 532 * fsm_rconfack - Receive Configure-Ack.
mbed714 0:d616ece2d859 533 */
mbed714 0:d616ece2d859 534 static void
mbed714 0:d616ece2d859 535 fsm_rconfack(fsm *f, int id, u_char *inp, int len)
mbed714 0:d616ece2d859 536 {
mbed714 0:d616ece2d859 537 FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
mbed714 0:d616ece2d859 538 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 539
mbed714 0:d616ece2d859 540 if (id != f->reqid || f->seen_ack) { /* Expected id? */
mbed714 0:d616ece2d859 541 return; /* Nope, toss... */
mbed714 0:d616ece2d859 542 }
mbed714 0:d616ece2d859 543 if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) {
mbed714 0:d616ece2d859 544 /* Ack is bad - ignore it */
mbed714 0:d616ece2d859 545 FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n",
mbed714 0:d616ece2d859 546 PROTO_NAME(f), len));
mbed714 0:d616ece2d859 547 return;
mbed714 0:d616ece2d859 548 }
mbed714 0:d616ece2d859 549 f->seen_ack = 1;
mbed714 0:d616ece2d859 550
mbed714 0:d616ece2d859 551 switch (f->state) {
mbed714 0:d616ece2d859 552 case LS_CLOSED:
mbed714 0:d616ece2d859 553 case LS_STOPPED:
mbed714 0:d616ece2d859 554 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
mbed714 0:d616ece2d859 555 break;
mbed714 0:d616ece2d859 556
mbed714 0:d616ece2d859 557 case LS_REQSENT:
mbed714 0:d616ece2d859 558 f->state = LS_ACKRCVD;
mbed714 0:d616ece2d859 559 f->retransmits = f->maxconfreqtransmits;
mbed714 0:d616ece2d859 560 break;
mbed714 0:d616ece2d859 561
mbed714 0:d616ece2d859 562 case LS_ACKRCVD:
mbed714 0:d616ece2d859 563 /* Huh? an extra valid Ack? oh well... */
mbed714 0:d616ece2d859 564 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 565 fsm_sconfreq(f, 0);
mbed714 0:d616ece2d859 566 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 567 break;
mbed714 0:d616ece2d859 568
mbed714 0:d616ece2d859 569 case LS_ACKSENT:
mbed714 0:d616ece2d859 570 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 571 f->state = LS_OPENED;
mbed714 0:d616ece2d859 572 f->retransmits = f->maxconfreqtransmits;
mbed714 0:d616ece2d859 573 if (f->callbacks->up) {
mbed714 0:d616ece2d859 574 (*f->callbacks->up)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 575 }
mbed714 0:d616ece2d859 576 break;
mbed714 0:d616ece2d859 577
mbed714 0:d616ece2d859 578 case LS_OPENED:
mbed714 0:d616ece2d859 579 /* Go down and restart negotiation */
mbed714 0:d616ece2d859 580 if (f->callbacks->down) {
mbed714 0:d616ece2d859 581 (*f->callbacks->down)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 582 }
mbed714 0:d616ece2d859 583 fsm_sconfreq(f, 0); /* Send initial Configure-Request */
mbed714 0:d616ece2d859 584 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 585 break;
mbed714 0:d616ece2d859 586 }
mbed714 0:d616ece2d859 587 }
mbed714 0:d616ece2d859 588
mbed714 0:d616ece2d859 589
mbed714 0:d616ece2d859 590 /*
mbed714 0:d616ece2d859 591 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
mbed714 0:d616ece2d859 592 */
mbed714 0:d616ece2d859 593 static void
mbed714 0:d616ece2d859 594 fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
mbed714 0:d616ece2d859 595 {
mbed714 0:d616ece2d859 596 int (*proc) (fsm *, u_char *, int);
mbed714 0:d616ece2d859 597 int ret;
mbed714 0:d616ece2d859 598
mbed714 0:d616ece2d859 599 FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
mbed714 0:d616ece2d859 600 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 601
mbed714 0:d616ece2d859 602 if (id != f->reqid || f->seen_ack) { /* Expected id? */
mbed714 0:d616ece2d859 603 return; /* Nope, toss... */
mbed714 0:d616ece2d859 604 }
mbed714 0:d616ece2d859 605 proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
mbed714 0:d616ece2d859 606 if (!proc || !((ret = proc(f, inp, len)))) {
mbed714 0:d616ece2d859 607 /* Nak/reject is bad - ignore it */
mbed714 0:d616ece2d859 608 FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n",
mbed714 0:d616ece2d859 609 PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
mbed714 0:d616ece2d859 610 return;
mbed714 0:d616ece2d859 611 }
mbed714 0:d616ece2d859 612 f->seen_ack = 1;
mbed714 0:d616ece2d859 613
mbed714 0:d616ece2d859 614 switch (f->state) {
mbed714 0:d616ece2d859 615 case LS_CLOSED:
mbed714 0:d616ece2d859 616 case LS_STOPPED:
mbed714 0:d616ece2d859 617 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
mbed714 0:d616ece2d859 618 break;
mbed714 0:d616ece2d859 619
mbed714 0:d616ece2d859 620 case LS_REQSENT:
mbed714 0:d616ece2d859 621 case LS_ACKSENT:
mbed714 0:d616ece2d859 622 /* They didn't agree to what we wanted - try another request */
mbed714 0:d616ece2d859 623 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 624 if (ret < 0) {
mbed714 0:d616ece2d859 625 f->state = LS_STOPPED; /* kludge for stopping CCP */
mbed714 0:d616ece2d859 626 } else {
mbed714 0:d616ece2d859 627 fsm_sconfreq(f, 0); /* Send Configure-Request */
mbed714 0:d616ece2d859 628 }
mbed714 0:d616ece2d859 629 break;
mbed714 0:d616ece2d859 630
mbed714 0:d616ece2d859 631 case LS_ACKRCVD:
mbed714 0:d616ece2d859 632 /* Got a Nak/reject when we had already had an Ack?? oh well... */
mbed714 0:d616ece2d859 633 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 634 fsm_sconfreq(f, 0);
mbed714 0:d616ece2d859 635 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 636 break;
mbed714 0:d616ece2d859 637
mbed714 0:d616ece2d859 638 case LS_OPENED:
mbed714 0:d616ece2d859 639 /* Go down and restart negotiation */
mbed714 0:d616ece2d859 640 if (f->callbacks->down) {
mbed714 0:d616ece2d859 641 (*f->callbacks->down)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 642 }
mbed714 0:d616ece2d859 643 fsm_sconfreq(f, 0); /* Send initial Configure-Request */
mbed714 0:d616ece2d859 644 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 645 break;
mbed714 0:d616ece2d859 646 }
mbed714 0:d616ece2d859 647 }
mbed714 0:d616ece2d859 648
mbed714 0:d616ece2d859 649
mbed714 0:d616ece2d859 650 /*
mbed714 0:d616ece2d859 651 * fsm_rtermreq - Receive Terminate-Req.
mbed714 0:d616ece2d859 652 */
mbed714 0:d616ece2d859 653 static void
mbed714 0:d616ece2d859 654 fsm_rtermreq(fsm *f, int id, u_char *p, int len)
mbed714 0:d616ece2d859 655 {
mbed714 0:d616ece2d859 656 LWIP_UNUSED_ARG(p);
mbed714 0:d616ece2d859 657
mbed714 0:d616ece2d859 658 FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
mbed714 0:d616ece2d859 659 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 660
mbed714 0:d616ece2d859 661 switch (f->state) {
mbed714 0:d616ece2d859 662 case LS_ACKRCVD:
mbed714 0:d616ece2d859 663 case LS_ACKSENT:
mbed714 0:d616ece2d859 664 f->state = LS_REQSENT; /* Start over but keep trying */
mbed714 0:d616ece2d859 665 break;
mbed714 0:d616ece2d859 666
mbed714 0:d616ece2d859 667 case LS_OPENED:
mbed714 0:d616ece2d859 668 if (len > 0) {
mbed714 0:d616ece2d859 669 FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p));
mbed714 0:d616ece2d859 670 } else {
mbed714 0:d616ece2d859 671 FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f)));
mbed714 0:d616ece2d859 672 }
mbed714 0:d616ece2d859 673 if (f->callbacks->down) {
mbed714 0:d616ece2d859 674 (*f->callbacks->down)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 675 }
mbed714 0:d616ece2d859 676 f->retransmits = 0;
mbed714 0:d616ece2d859 677 f->state = LS_STOPPING;
mbed714 0:d616ece2d859 678 TIMEOUT(fsm_timeout, f, f->timeouttime);
mbed714 0:d616ece2d859 679 break;
mbed714 0:d616ece2d859 680 }
mbed714 0:d616ece2d859 681
mbed714 0:d616ece2d859 682 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
mbed714 0:d616ece2d859 683 }
mbed714 0:d616ece2d859 684
mbed714 0:d616ece2d859 685
mbed714 0:d616ece2d859 686 /*
mbed714 0:d616ece2d859 687 * fsm_rtermack - Receive Terminate-Ack.
mbed714 0:d616ece2d859 688 */
mbed714 0:d616ece2d859 689 static void
mbed714 0:d616ece2d859 690 fsm_rtermack(fsm *f)
mbed714 0:d616ece2d859 691 {
mbed714 0:d616ece2d859 692 FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n",
mbed714 0:d616ece2d859 693 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 694
mbed714 0:d616ece2d859 695 switch (f->state) {
mbed714 0:d616ece2d859 696 case LS_CLOSING:
mbed714 0:d616ece2d859 697 UNTIMEOUT(fsm_timeout, f);
mbed714 0:d616ece2d859 698 f->state = LS_CLOSED;
mbed714 0:d616ece2d859 699 if( f->callbacks->finished ) {
mbed714 0:d616ece2d859 700 (*f->callbacks->finished)(f);
mbed714 0:d616ece2d859 701 }
mbed714 0:d616ece2d859 702 break;
mbed714 0:d616ece2d859 703
mbed714 0:d616ece2d859 704 case LS_STOPPING:
mbed714 0:d616ece2d859 705 UNTIMEOUT(fsm_timeout, f);
mbed714 0:d616ece2d859 706 f->state = LS_STOPPED;
mbed714 0:d616ece2d859 707 if( f->callbacks->finished ) {
mbed714 0:d616ece2d859 708 (*f->callbacks->finished)(f);
mbed714 0:d616ece2d859 709 }
mbed714 0:d616ece2d859 710 break;
mbed714 0:d616ece2d859 711
mbed714 0:d616ece2d859 712 case LS_ACKRCVD:
mbed714 0:d616ece2d859 713 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 714 break;
mbed714 0:d616ece2d859 715
mbed714 0:d616ece2d859 716 case LS_OPENED:
mbed714 0:d616ece2d859 717 if (f->callbacks->down) {
mbed714 0:d616ece2d859 718 (*f->callbacks->down)(f); /* Inform upper layers */
mbed714 0:d616ece2d859 719 }
mbed714 0:d616ece2d859 720 fsm_sconfreq(f, 0);
mbed714 0:d616ece2d859 721 break;
mbed714 0:d616ece2d859 722 default:
mbed714 0:d616ece2d859 723 FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n",
mbed714 0:d616ece2d859 724 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 725 }
mbed714 0:d616ece2d859 726 }
mbed714 0:d616ece2d859 727
mbed714 0:d616ece2d859 728
mbed714 0:d616ece2d859 729 /*
mbed714 0:d616ece2d859 730 * fsm_rcoderej - Receive an Code-Reject.
mbed714 0:d616ece2d859 731 */
mbed714 0:d616ece2d859 732 static void
mbed714 0:d616ece2d859 733 fsm_rcoderej(fsm *f, u_char *inp, int len)
mbed714 0:d616ece2d859 734 {
mbed714 0:d616ece2d859 735 u_char code, id;
mbed714 0:d616ece2d859 736
mbed714 0:d616ece2d859 737 FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n",
mbed714 0:d616ece2d859 738 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 739
mbed714 0:d616ece2d859 740 if (len < HEADERLEN) {
mbed714 0:d616ece2d859 741 FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
mbed714 0:d616ece2d859 742 return;
mbed714 0:d616ece2d859 743 }
mbed714 0:d616ece2d859 744 GETCHAR(code, inp);
mbed714 0:d616ece2d859 745 GETCHAR(id, inp);
mbed714 0:d616ece2d859 746 FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n",
mbed714 0:d616ece2d859 747 PROTO_NAME(f), code, id));
mbed714 0:d616ece2d859 748
mbed714 0:d616ece2d859 749 if( f->state == LS_ACKRCVD ) {
mbed714 0:d616ece2d859 750 f->state = LS_REQSENT;
mbed714 0:d616ece2d859 751 }
mbed714 0:d616ece2d859 752 }
mbed714 0:d616ece2d859 753
mbed714 0:d616ece2d859 754
mbed714 0:d616ece2d859 755 /*
mbed714 0:d616ece2d859 756 * fsm_protreject - Peer doesn't speak this protocol.
mbed714 0:d616ece2d859 757 *
mbed714 0:d616ece2d859 758 * Treat this as a catastrophic error (RXJ-).
mbed714 0:d616ece2d859 759 */
mbed714 0:d616ece2d859 760 void
mbed714 0:d616ece2d859 761 fsm_protreject(fsm *f)
mbed714 0:d616ece2d859 762 {
mbed714 0:d616ece2d859 763 switch( f->state ) {
mbed714 0:d616ece2d859 764 case LS_CLOSING:
mbed714 0:d616ece2d859 765 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 766 /* fall through */
mbed714 0:d616ece2d859 767 case LS_CLOSED:
mbed714 0:d616ece2d859 768 f->state = LS_CLOSED;
mbed714 0:d616ece2d859 769 if( f->callbacks->finished ) {
mbed714 0:d616ece2d859 770 (*f->callbacks->finished)(f);
mbed714 0:d616ece2d859 771 }
mbed714 0:d616ece2d859 772 break;
mbed714 0:d616ece2d859 773
mbed714 0:d616ece2d859 774 case LS_STOPPING:
mbed714 0:d616ece2d859 775 case LS_REQSENT:
mbed714 0:d616ece2d859 776 case LS_ACKRCVD:
mbed714 0:d616ece2d859 777 case LS_ACKSENT:
mbed714 0:d616ece2d859 778 UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
mbed714 0:d616ece2d859 779 /* fall through */
mbed714 0:d616ece2d859 780 case LS_STOPPED:
mbed714 0:d616ece2d859 781 f->state = LS_STOPPED;
mbed714 0:d616ece2d859 782 if( f->callbacks->finished ) {
mbed714 0:d616ece2d859 783 (*f->callbacks->finished)(f);
mbed714 0:d616ece2d859 784 }
mbed714 0:d616ece2d859 785 break;
mbed714 0:d616ece2d859 786
mbed714 0:d616ece2d859 787 case LS_OPENED:
mbed714 0:d616ece2d859 788 if( f->callbacks->down ) {
mbed714 0:d616ece2d859 789 (*f->callbacks->down)(f);
mbed714 0:d616ece2d859 790 }
mbed714 0:d616ece2d859 791 /* Init restart counter, send Terminate-Request */
mbed714 0:d616ece2d859 792 f->retransmits = f->maxtermtransmits;
mbed714 0:d616ece2d859 793 fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
mbed714 0:d616ece2d859 794 (u_char *) f->term_reason, f->term_reason_len);
mbed714 0:d616ece2d859 795 TIMEOUT(fsm_timeout, f, f->timeouttime);
mbed714 0:d616ece2d859 796 --f->retransmits;
mbed714 0:d616ece2d859 797
mbed714 0:d616ece2d859 798 f->state = LS_STOPPING;
mbed714 0:d616ece2d859 799 break;
mbed714 0:d616ece2d859 800
mbed714 0:d616ece2d859 801 default:
mbed714 0:d616ece2d859 802 FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n",
mbed714 0:d616ece2d859 803 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
mbed714 0:d616ece2d859 804 }
mbed714 0:d616ece2d859 805 }
mbed714 0:d616ece2d859 806
mbed714 0:d616ece2d859 807
mbed714 0:d616ece2d859 808 /*
mbed714 0:d616ece2d859 809 * fsm_sconfreq - Send a Configure-Request.
mbed714 0:d616ece2d859 810 */
mbed714 0:d616ece2d859 811 static void
mbed714 0:d616ece2d859 812 fsm_sconfreq(fsm *f, int retransmit)
mbed714 0:d616ece2d859 813 {
mbed714 0:d616ece2d859 814 u_char *outp;
mbed714 0:d616ece2d859 815 int cilen;
mbed714 0:d616ece2d859 816
mbed714 0:d616ece2d859 817 if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) {
mbed714 0:d616ece2d859 818 /* Not currently negotiating - reset options */
mbed714 0:d616ece2d859 819 if( f->callbacks->resetci ) {
mbed714 0:d616ece2d859 820 (*f->callbacks->resetci)(f);
mbed714 0:d616ece2d859 821 }
mbed714 0:d616ece2d859 822 f->nakloops = 0;
mbed714 0:d616ece2d859 823 }
mbed714 0:d616ece2d859 824
mbed714 0:d616ece2d859 825 if( !retransmit ) {
mbed714 0:d616ece2d859 826 /* New request - reset retransmission counter, use new ID */
mbed714 0:d616ece2d859 827 f->retransmits = f->maxconfreqtransmits;
mbed714 0:d616ece2d859 828 f->reqid = ++f->id;
mbed714 0:d616ece2d859 829 }
mbed714 0:d616ece2d859 830
mbed714 0:d616ece2d859 831 f->seen_ack = 0;
mbed714 0:d616ece2d859 832
mbed714 0:d616ece2d859 833 /*
mbed714 0:d616ece2d859 834 * Make up the request packet
mbed714 0:d616ece2d859 835 */
mbed714 0:d616ece2d859 836 outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN;
mbed714 0:d616ece2d859 837 if( f->callbacks->cilen && f->callbacks->addci ) {
mbed714 0:d616ece2d859 838 cilen = (*f->callbacks->cilen)(f);
mbed714 0:d616ece2d859 839 if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) {
mbed714 0:d616ece2d859 840 cilen = peer_mru[f->unit] - HEADERLEN;
mbed714 0:d616ece2d859 841 }
mbed714 0:d616ece2d859 842 if (f->callbacks->addci) {
mbed714 0:d616ece2d859 843 (*f->callbacks->addci)(f, outp, &cilen);
mbed714 0:d616ece2d859 844 }
mbed714 0:d616ece2d859 845 } else {
mbed714 0:d616ece2d859 846 cilen = 0;
mbed714 0:d616ece2d859 847 }
mbed714 0:d616ece2d859 848
mbed714 0:d616ece2d859 849 /* send the request to our peer */
mbed714 0:d616ece2d859 850 fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
mbed714 0:d616ece2d859 851
mbed714 0:d616ece2d859 852 /* start the retransmit timer */
mbed714 0:d616ece2d859 853 --f->retransmits;
mbed714 0:d616ece2d859 854 TIMEOUT(fsm_timeout, f, f->timeouttime);
mbed714 0:d616ece2d859 855
mbed714 0:d616ece2d859 856 FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n",
mbed714 0:d616ece2d859 857 PROTO_NAME(f), f->reqid));
mbed714 0:d616ece2d859 858 }
mbed714 0:d616ece2d859 859
mbed714 0:d616ece2d859 860
mbed714 0:d616ece2d859 861 /*
mbed714 0:d616ece2d859 862 * fsm_sdata - Send some data.
mbed714 0:d616ece2d859 863 *
mbed714 0:d616ece2d859 864 * Used for all packets sent to our peer by this module.
mbed714 0:d616ece2d859 865 */
mbed714 0:d616ece2d859 866 void
mbed714 0:d616ece2d859 867 fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen)
mbed714 0:d616ece2d859 868 {
mbed714 0:d616ece2d859 869 u_char *outp;
mbed714 0:d616ece2d859 870 int outlen;
mbed714 0:d616ece2d859 871
mbed714 0:d616ece2d859 872 /* Adjust length to be smaller than MTU */
mbed714 0:d616ece2d859 873 outp = outpacket_buf[f->unit];
mbed714 0:d616ece2d859 874 if (datalen > peer_mru[f->unit] - (int)HEADERLEN) {
mbed714 0:d616ece2d859 875 datalen = peer_mru[f->unit] - HEADERLEN;
mbed714 0:d616ece2d859 876 }
mbed714 0:d616ece2d859 877 if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) {
mbed714 0:d616ece2d859 878 BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
mbed714 0:d616ece2d859 879 }
mbed714 0:d616ece2d859 880 outlen = datalen + HEADERLEN;
mbed714 0:d616ece2d859 881 MAKEHEADER(outp, f->protocol);
mbed714 0:d616ece2d859 882 PUTCHAR(code, outp);
mbed714 0:d616ece2d859 883 PUTCHAR(id, outp);
mbed714 0:d616ece2d859 884 PUTSHORT(outlen, outp);
mbed714 0:d616ece2d859 885 pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
mbed714 0:d616ece2d859 886 FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n",
mbed714 0:d616ece2d859 887 PROTO_NAME(f), code, id, outlen));
mbed714 0:d616ece2d859 888 }
mbed714 0:d616ece2d859 889
mbed714 0:d616ece2d859 890 #endif /* PPP_SUPPORT */