Library for Bert van Dam's book "ARM MICROCONTROLLERS" For all chapters with internet.

Dependencies:   mbed

Committer:
ICTFBI
Date:
Fri Oct 16 14:28:26 2015 +0000
Revision:
0:4edb816d21e1
Pre-update 16-10-15

Who changed what in which revision?

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