176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/***************************************************************************** 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* fsm.c - Network Control Protocol Finite State Machine program file. 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* portions Copyright (c) 1997 by Global Election Systems Inc. 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* The authors hereby grant permission to use, copy, modify, distribute, 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* and license this software and its documentation for any purpose, provided 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* that existing copyright notices are retained in all copies and that this 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* notice and the following disclaimer are included verbatim in any 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* distributions. No written agreement, license, or royalty fee is required 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* for any of the authorized uses. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman****************************************************************************** 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* REVISION HISTORY 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 03-01-01 Marc Boucher <marc@mbsi.ca> 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Ported to lwIP. 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Original based on BSD fsm.c. 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*****************************************************************************/ 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm.c - {Link, IP} Control Protocol Finite State Machine. 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 1989 Carnegie Mellon University. 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * All rights reserved. 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Redistribution and use in source and binary forms are permitted 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * provided that the above copyright notice and this paragraph are 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * duplicated in all such forms and that any documentation, 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * advertising materials, and other materials related to such 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * distribution and use acknowledge that the software was developed 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * by Carnegie Mellon University. The name of the 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * University may not be used to endorse or promote products derived 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * from this software without specific prior written permission. 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * TODO: 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Randomize fsm id on link/init. 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Deal with variable outgoing MTU. 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lwip/opt.h" 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "ppp.h" 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "pppdebug.h" 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "fsm.h" 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_DEBUG 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *ppperr_strerr[] = { 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_INITIAL", /* LS_INITIAL 0 */ 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_STARTING", /* LS_STARTING 1 */ 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_CLOSED", /* LS_CLOSED 2 */ 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_STOPPED", /* LS_STOPPED 3 */ 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_CLOSING", /* LS_CLOSING 4 */ 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_STOPPING", /* LS_STOPPING 5 */ 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_REQSENT", /* LS_REQSENT 6 */ 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_ACKRCVD", /* LS_ACKRCVD 7 */ 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_ACKSENT", /* LS_ACKSENT 8 */ 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "LS_OPENED" /* LS_OPENED 9 */ 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PPP_DEBUG */ 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_timeout (void *); 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_rconfreq (fsm *, u_char, u_char *, int); 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_rconfack (fsm *, int, u_char *, int); 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_rconfnakrej (fsm *, int, int, u_char *, int); 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_rtermreq (fsm *, int, u_char *, int); 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_rtermack (fsm *); 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_rcoderej (fsm *, u_char *, int); 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void fsm_sconfreq (fsm *, int); 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PROTO_NAME(f) ((f)->callbacks->proto_name) 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint peer_mru[NUM_PPP]; 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_init - Initialize fsm. 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Initialize fsm state. 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_init(fsm *f) 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_INITIAL; 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->flags = 0; 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->id = 0; /* XXX Start with random id? */ 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->timeouttime = FSM_DEFTIMEOUT; 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->maxconfreqtransmits = FSM_DEFMAXCONFREQS; 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->maxtermtransmits = FSM_DEFMAXTERMREQS; 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->maxnakloops = FSM_DEFMAXNAKLOOPS; 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->term_reason_len = 0; 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_lowerup - The lower layer is up. 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_lowerup(fsm *f) 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int oldState = f->state; 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LWIP_UNUSED_ARG(oldState); 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch( f->state ) { 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_INITIAL: 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_CLOSED; 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STARTING: 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->flags & OPT_SILENT ) { 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPED; 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Send an initial configure-request */ 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_lowerdown - The lower layer is down. 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Cancel all timeouts and inform upper layers. 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_lowerdown(fsm *f) 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int oldState = f->state; 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LWIP_UNUSED_ARG(oldState); 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch( f->state ) { 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSED: 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_INITIAL; 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STARTING; 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->starting ) { 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->starting)(f); 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSING: 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_INITIAL; 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPING: 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_REQSENT: 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STARTING; 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->down ) { 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STARTING; 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_open - Link is allowed to come up. 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_open(fsm *f) 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int oldState = f->state; 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LWIP_UNUSED_ARG(oldState); 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch( f->state ) { 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_INITIAL: 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STARTING; 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->starting ) { 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->starting)(f); 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSED: 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->flags & OPT_SILENT ) { 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPED; 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Send an initial configure-request */ 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSING: 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPING; 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* fall through */ 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->flags & OPT_RESTART ) { 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_lowerdown(f); 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_lowerup(f); 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 /* backport pppd 2.4.4b1; */ 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * terminate_layer - Start process of shutting down the FSM 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Cancel any timeout running, notify upper layers we're done, and 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * send a terminate-request message as configured. 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanterminate_layer(fsm *f, int nextstate) 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* @todo */ 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_close - Start closing connection. 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Cancel timeouts and either initiate close or possibly go directly to 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the LS_CLOSED state. 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_close(fsm *f, char *reason) 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int oldState = f->state; 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LWIP_UNUSED_ARG(oldState); 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->term_reason = reason; 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason)); 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch( f->state ) { 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STARTING: 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_INITIAL; 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_CLOSED; 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPING: 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_CLOSING; 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_REQSENT: 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->state != LS_OPENED ) { 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if( f->callbacks->down ) { 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); /* Inform upper layers we're down */ 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Init restart counter, send Terminate-Request */ 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->retransmits = f->maxtermtransmits; 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (u_char *) f->term_reason, f->term_reason_len); 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TIMEOUT(fsm_timeout, f, f->timeouttime); 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman --f->retransmits; 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_CLOSING; 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_timeout - Timeout expired. 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_timeout(void *arg) 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm *f = (fsm *) arg; 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (f->state) { 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSING: 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPING: 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->retransmits <= 0 ) { 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We've waited for an ack long enough. Peer probably heard us. 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->finished ) { 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->finished)(f); 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Send Terminate-Request */ 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (u_char *) f->term_reason, f->term_reason_len); 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TIMEOUT(fsm_timeout, f, f->timeouttime); 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman --f->retransmits; 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_REQSENT: 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->retransmits <= 0) { 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPED; 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->finished)(f); 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Retransmit the configure-request */ 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->retransmit) { 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->retransmit)(f); 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 1); /* Re-send Configure-Request */ 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->state == LS_ACKRCVD ) { 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_input - Input packet. 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_input(fsm *f, u_char *inpacket, int l) 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u_char *inp = inpacket; 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u_char code, id; 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int len; 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse header (code, id and length). 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * If packet too short, drop it. 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (l < HEADERLEN) { 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", 39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->protocol)); 39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GETCHAR(code, inp); 39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GETCHAR(id, inp); 39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GETSHORT(len, inp); 40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (len < HEADERLEN) { 40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", 40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->protocol)); 40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (len > l) { 40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", 40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->protocol)); 40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len -= HEADERLEN; /* subtract header length */ 41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->state == LS_INITIAL || f->state == LS_STARTING ) { 41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", 41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->protocol, f->state, ppperr_strerr[f->state])); 41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); 41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Action depends on code. 42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (code) { 42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case CONFREQ: 42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_rconfreq(f, id, inp, len); 42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case CONFACK: 42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_rconfack(f, id, inp, len); 42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case CONFNAK: 43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case CONFREJ: 43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_rconfnakrej(f, code, id, inp, len); 43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case TERMREQ: 43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_rtermreq(f, id, inp, len); 43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case TERMACK: 44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_rtermack(f); 44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case CODEREJ: 44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_rcoderej(f, inp, len); 44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); 44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( !f->callbacks->extcode || 45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman !(*f->callbacks->extcode)(f, code, id, inp, len) ) { 45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); 45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_rconfreq - Receive Configure-Request. 46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) 46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int code, reject_if_disagree; 46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", 46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch( f->state ) { 46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSED: 47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Go away, we're closed */ 47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMACK, id, NULL, 0); 47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSING: 47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPING: 47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Go down and restart negotiation */ 47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->down ) { 48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); /* Inform upper layers */ 48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Negotiation started by our peer */ 48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Pass the requested configuration options 49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to protocol-specific code for checking. 49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->reqci) { /* Check CI */ 49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman reject_if_disagree = (f->nakloops >= f->maxnakloops); 49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); 49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (len) { 50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman code = CONFREJ; /* Reject all CI */ 50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman code = CONFACK; 50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* send the Ack, Nak or Rej to the peer */ 50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, (u_char)code, id, inp, len); 50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (code == CONFACK) { 50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->state == LS_ACKRCVD) { 51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_OPENED; 51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->up) { 51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->up)(f); /* Inform upper layers */ 51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_ACKSENT; 51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->nakloops = 0; 51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* we sent CONFACK or CONFREJ */ 52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->state != LS_ACKRCVD) { 52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( code == CONFNAK ) { 52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ++f->nakloops; 52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_rconfack - Receive Configure-Ack. 53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_rconfack(fsm *f, int id, u_char *inp, int len) 53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", 53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (id != f->reqid || f->seen_ack) { /* Expected id? */ 54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; /* Nope, toss... */ 54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { 54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Ack is bad - ignore it */ 54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", 54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), len)); 54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->seen_ack = 1; 55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (f->state) { 55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSED: 55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_REQSENT: 55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_ACKRCVD; 55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->retransmits = f->maxconfreqtransmits; 56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Huh? an extra valid Ack? oh well... */ 56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); 56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_OPENED; 57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->retransmits = f->maxconfreqtransmits; 57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->up) { 57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->up)(f); /* Inform upper layers */ 57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Go down and restart negotiation */ 58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->down) { 58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); /* Inform upper layers */ 58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) 59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int (*proc) (fsm *, u_char *, int); 59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ret; 59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", 60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (id != f->reqid || f->seen_ack) { /* Expected id? */ 60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; /* Nope, toss... */ 60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; 60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!proc || !((ret = proc(f, inp, len)))) { 60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Nak/reject is bad - ignore it */ 60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", 60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); 61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->seen_ack = 1; 61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (f->state) { 61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSED: 61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_REQSENT: 62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* They didn't agree to what we wanted - try another request */ 62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ret < 0) { 62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPED; /* kludge for stopping CCP */ 62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); /* Send Configure-Request */ 62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Got a Nak/reject when we had already had an Ack?? oh well... */ 63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); 63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Go down and restart negotiation */ 64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->down) { 64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); /* Inform upper layers */ 64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); /* Send initial Configure-Request */ 64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_rtermreq - Receive Terminate-Req. 65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_rtermreq(fsm *f, int id, u_char *p, int len) 65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LWIP_UNUSED_ARG(p); 65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", 65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); 66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (f->state) { 66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; /* Start over but keep trying */ 66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (len > 0) { 66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); 67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); 67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->down) { 67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); /* Inform upper layers */ 67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->retransmits = 0; 67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPING; 67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TIMEOUT(fsm_timeout, f, f->timeouttime); 67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); 68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_rtermack - Receive Terminate-Ack. 68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_rtermack(fsm *f) 69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", 69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (f->state) { 69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSING: 69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); 69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_CLOSED; 69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->finished ) { 70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->finished)(f); 70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPING: 70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); 70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPED; 70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->finished ) { 70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->finished)(f); 70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->down) { 71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); /* Inform upper layers */ 71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sconfreq(f, 0); 72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", 72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_rcoderej - Receive an Code-Reject. 73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_rcoderej(fsm *f, u_char *inp, int len) 73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u_char code, id; 73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", 73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (len < HEADERLEN) { 74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); 74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GETCHAR(code, inp); 74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GETCHAR(id, inp); 74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", 74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), code, id)); 74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->state == LS_ACKRCVD ) { 75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_REQSENT; 75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_protreject - Peer doesn't speak this protocol. 75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Treat this as a catastrophic error (RXJ-). 75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_protreject(fsm *f) 76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch( f->state ) { 76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSING: 76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* fall through */ 76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_CLOSED: 76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_CLOSED; 76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->finished ) { 77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->finished)(f); 77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPING: 77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_REQSENT: 77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKRCVD: 77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_ACKSENT: 77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ 77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* fall through */ 78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_STOPPED: 78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPED; 78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->finished ) { 78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->finished)(f); 78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LS_OPENED: 78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->down ) { 78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->down)(f); 79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Init restart counter, send Terminate-Request */ 79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->retransmits = f->maxtermtransmits; 79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, TERMREQ, f->reqid = ++f->id, 79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (u_char *) f->term_reason, f->term_reason_len); 79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TIMEOUT(fsm_timeout, f, f->timeouttime); 79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman --f->retransmits; 79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->state = LS_STOPPING; 79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", 80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->state, ppperr_strerr[f->state])); 80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_sconfreq - Send a Configure-Request. 81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_sconfreq(fsm *f, int retransmit) 81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u_char *outp; 81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int cilen; 81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { 81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Not currently negotiating - reset options */ 81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->resetci ) { 82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->resetci)(f); 82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->nakloops = 0; 82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( !retransmit ) { 82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* New request - reset retransmission counter, use new ID */ 82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->retransmits = f->maxconfreqtransmits; 82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->reqid = ++f->id; 82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f->seen_ack = 0; 83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Make up the request packet 83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; 83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( f->callbacks->cilen && f->callbacks->addci ) { 83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cilen = (*f->callbacks->cilen)(f); 83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { 84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cilen = peer_mru[f->unit] - HEADERLEN; 84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f->callbacks->addci) { 84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (*f->callbacks->addci)(f, outp, &cilen); 84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cilen = 0; 84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* send the request to our peer */ 85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); 85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* start the retransmit timer */ 85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman --f->retransmits; 85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TIMEOUT(fsm_timeout, f, f->timeouttime); 85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", 85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), f->reqid)); 85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fsm_sdata - Send some data. 86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Used for all packets sent to our peer by this module. 86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid 86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) 86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u_char *outp; 87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int outlen; 87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Adjust length to be smaller than MTU */ 87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outp = outpacket_buf[f->unit]; 87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { 87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman datalen = peer_mru[f->unit] - HEADERLEN; 87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { 87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); 87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outlen = datalen + HEADERLEN; 88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MAKEHEADER(outp, f->protocol); 88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PUTCHAR(code, outp); 88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PUTCHAR(id, outp); 88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PUTSHORT(outlen, outp); 88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); 88676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", 88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PROTO_NAME(f), code, id, outlen)); 88876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PPP_SUPPORT */ 891