HTTPClient using static IP

Dependencies:   mbed

Committer:
mr_q
Date:
Mon May 30 11:53:37 2011 +0000
Revision:
0:d8f2f7d5f31b
v0.01 Draft

Who changed what in which revision?

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