Web server based weather station using Sparkfun Weather Meters.

Dependencies:   FatFileSystem mbed WeatherMeters SDFileSystem

Committer:
AdamGreen
Date:
Sat Feb 25 03:28:05 2012 +0000
Revision:
1:c7958aa34fa1
Parent:
0:616601bde9fb
Use published libraries where possible.

Who changed what in which revision?

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