I have a problem getting this to work. Server only recieves half of the data being sent. Whats wrong

Dependencies:   mbed

Committer:
tax
Date:
Tue Mar 29 13:20:15 2011 +0000
Revision:
0:66300c77c6e9

        

Who changed what in which revision?

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