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