LwIP with PPP & Ethernet integration

Dependents:   NetworkingCoreLib

This is the mbed port of the LwIP stack: http://savannah.nongnu.org/projects/lwip/

It includes contributed content from NXP's port for LPCxxxx devices: http://www.lpcware.com/content/project/lightweight-ip-lwip-networking-stack

Licence

LwIP is licenced under the BSD licence:

Copyright (c) 2001-2004 Swedish Institute of Computer Science. 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met: 
1. Redistributions of source code must retain the above copyright notice, 
this list of conditions and the following disclaimer. 
2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution. 
3. The name of the author may not be used to endorse or promote products 
derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
donatien
Date:
Fri May 25 08:56:35 2012 +0000
Revision:
2:1a87f74b8e3b
Parent:
0:8e01dca41002
Removed compilation of EMAC driver when using PPP

Who changed what in which revision?

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