Embedded C project:18/12/2014

Dependencies:   DS1307 TextLCD mbed

Committer:
ninoderkinderen
Date:
Thu Dec 18 09:35:49 2014 +0000
Revision:
0:8d87bc453349
Programma embedded C

Who changed what in which revision?

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