Example self-announcing webserver which controls a servo through a smallHTML userinterface.

Dependencies:   mbed

Committer:
dirkx
Date:
Sat Aug 14 15:56:01 2010 +0000
Revision:
0:a259777c45a3

        

Who changed what in which revision?

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