0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-05-05 13:17:53 +00:00
Files
2022-01-04 12:22:53 +02:00

1264 lines
32 KiB
C

/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: pppfsm.c$
* $Version : 3.8.7.0$
* $Date : Aug-22-2012$
*
* Comments:
*
* This file contains the implementation for the
* {Link, IP} Control Protocol Finite State Machine.
*
*END************************************************************************/
/*
** fsm.c - {Link, IP} Control Protocol Finite State Machine.
**
** Copyright (c) 1989 Carnegie Mellon University.
** All rights reserved.
**
** Redistribution and use in source and binary forms are permitted
** provided that the above copyright notice and this paragraph are
** duplicated in all such forms and that any documentation,
** advertising materials, and other materials related to such
** distribution and use acknowledge that the software was developed
** by Carnegie Mellon University. The name of the
** University may not be used to endorse or promote products derived
** from this software without specific prior written permission.
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <ppp.h>
#include "ppp_prv.h"
static void PPPFSM_buildheader(PPPFSM_CFG_PTR, PCB_PTR, uchar, boolean, uint_32);
static void PPPFSM_timeout(pointer, PCB_PTR, boolean);
static void PPPFSM_recvconfreq(PPPFSM_CFG_PTR, _ppp_handle);
static void PPPFSM_recvconfack(PPPFSM_CFG_PTR);
static void PPPFSM_recvconfnak(PPPFSM_CFG_PTR, boolean(_CODE_PTR_)(PPPFSM_CFG_PTR));
static void PPPFSM_recvtermreq(PPPFSM_CFG_PTR);
static void PPPFSM_recvtermack(PPPFSM_CFG_PTR);
static void PPPFSM_recvcoderej(PPPFSM_CFG_PTR);
static void PPPFSM_sendconfrep(PPPFSM_CFG_PTR, uint_32);
static void PPPFSM_sendtermack(PPPFSM_CFG_PTR, boolean);
static void PPPFSM_sendcoderej(PPPFSM_CFG_PTR);
static void PPPFSM_sendconfreq(PPPFSM_CFG_PTR, PCB_PTR);
static void PPPFSM_sendtermreq(PPPFSM_CFG_PTR, PCB_PTR);
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_init
* Returned Value : error code
* Comments :
* Called by application. Initializes the Finite State Machine.
*
*END*-----------------------------------------------------------------*/
uint_32 PPPFSM_init
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
_ppp_handle handle,
/* [IN] - the PPP state structure */
PPPFSM_CALL_PTR call_ptr,
/* [IN] - Protocol-specific call table */
pointer param
/* [IN] - Parameter for protocol-specific calls */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
PPP_memzero(fsm, sizeof(PPPFSM_CFG));
fsm->HANDLE = handle;
fsm->CALL = call_ptr;
fsm->PRIVATE = param;
fsm->STATE = PPP_STATE_INITIAL;
fsm->CURID = RTCS_rand() & 0xFF;
/* Initialize the mutex */
if (PPP_mutex_init(&fsm->MUTEX)) {
return RTCSERR_PPP_INIT_MUTEX_FAILED;
} /* Endif */
return PPP_OK;
#else
return RTCSERR_IP_IS_DISABLED;
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_destroy
* Returned Value : error code
* Comments :
* Called by application. Destroys the Finite State Machine.
* Assumes the Finite State Machine has been initialized.
*
*END*-----------------------------------------------------------------*/
uint_32 PPPFSM_destroy
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
uint_32 error = PPP_OK;
PPP_mutex_lock(&fsm->MUTEX);
if (fsm->STATE > PPP_STATE_CLOSED) {
error = RTCSERR_PPP_FSM_ACTIVE;
} else {
fsm->STATE = PPP_STATE_INITIAL;
} /* Endif */
PPP_mutex_unlock(&fsm->MUTEX);
if (!error) {
PPP_mutex_destroy(&fsm->MUTEX);
} /* Endif */
return error;
#else
return RTCSERR_IP_IS_DISABLED;
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_lowerup
* Returned Value : void
* Comments :
* Lower layer is up.
*
*END*-----------------------------------------------------------------*/
void PPPFSM_lowerup
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
PPP_mutex_lock(&fsm->MUTEX);
switch(fsm->STATE) {
case PPP_STATE_INITIAL:
fsm->STATE = PPP_STATE_CLOSED;
break;
case PPP_STATE_STARTING:
if (fsm->OPTIONS & PPP_OPT_SILENT) {
fsm->STATE = PPP_STATE_STOPPED;
} else {
PPPFSM_sendconfreq(fsm, NULL);
fsm->STATE = PPP_STATE_REQ_SENT;
}/* Endif */
break;
} /* Endswitch */
PPP_mutex_unlock(&fsm->MUTEX);
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_lowerdown
* Returned Value : void
* Comments :
* Cancel all timeouts and inform upper layers. Lower layer is
* down.
*
*END*-----------------------------------------------------------------*/
void PPPFSM_lowerdown
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
PPP_mutex_lock(&fsm->MUTEX);
switch(fsm->STATE) {
case PPP_STATE_CLOSED:
fsm->STATE = PPP_STATE_INITIAL;
break;
case PPP_STATE_STOPPED:
fsm->STATE = PPP_STATE_STARTING;
break;
case PPP_STATE_CLOSING:
fsm->STATE = PPP_STATE_INITIAL;
PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
break;
case PPP_STATE_STOPPING:
case PPP_STATE_REQ_SENT:
case PPP_STATE_ACK_RCVD:
case PPP_STATE_ACK_SENT:
fsm->STATE = PPP_STATE_STARTING;
PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
break;
case PPP_STATE_OPENED:
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
fsm->STATE = PPP_STATE_STARTING;
break;
} /* Endswitch */
PPP_mutex_unlock(&fsm->MUTEX);
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_open
* Returned Value : void
* Comments :
* Called by application. Begin negotiating the link.
*
*END*-----------------------------------------------------------------*/
void PPPFSM_open
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
uint_32 options
/* [IN] - Startup options */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
PPP_mutex_lock(&fsm->MUTEX);
fsm->OPTIONS = options;
switch (fsm->STATE) {
case PPP_STATE_INITIAL:
fsm->STATE = PPP_STATE_STARTING;
break;
case PPP_STATE_CLOSED:
if (options & PPP_OPT_SILENT) {
fsm->STATE = PPP_STATE_STOPPED;
} else {
/* Send an initial Configure-Request */
PPPFSM_sendconfreq(fsm, NULL);
fsm->STATE = PPP_STATE_REQ_SENT;
} /* Endif */
break;
case PPP_STATE_CLOSING:
fsm->STATE = PPP_STATE_STOPPING;
/* fall through */
case PPP_STATE_STOPPING:
case PPP_STATE_STOPPED:
if (options & PPP_OPT_RESTART) {
PPPFSM_sendconfreq(fsm, NULL);
fsm->STATE = PPP_STATE_REQ_SENT;
} /* Endif */
break;
case PPP_STATE_OPENED:
if (options & PPP_OPT_RESTART) {
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendconfreq(fsm, NULL);
fsm->STATE = PPP_STATE_REQ_SENT;
} /* Endif */
break;
} /* Endswitch */
PPP_mutex_unlock(&fsm->MUTEX);
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_close
* Returned Value : void
* Comments :
* Called by application. Begin closing the link.
*
*END*-----------------------------------------------------------------*/
void PPPFSM_close
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
PPP_mutex_lock(&fsm->MUTEX);
switch (fsm->STATE) {
case PPP_STATE_STARTING:
fsm->STATE = PPP_STATE_INITIAL;
break;
case PPP_STATE_STOPPED:
fsm->STATE = PPP_STATE_CLOSED;
break;
case PPP_STATE_STOPPING:
fsm->STATE = PPP_STATE_CLOSING;
break;
case PPP_STATE_OPENED:
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
/* fall through */
case PPP_STATE_REQ_SENT:
case PPP_STATE_ACK_RCVD:
case PPP_STATE_ACK_SENT:
PPPFSM_sendtermreq(fsm, NULL);
fsm->STATE = PPP_STATE_CLOSING;
break;
} /* Endswitch */
PPP_mutex_unlock(&fsm->MUTEX);
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_timeout
* Returned Value : void
* Comments :
* Called by PPP_tx_task. Timeout expired.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_timeout
(
pointer fsm_ptr,
/* [IN/OUT] - State Machine */
PCB_PTR packet,
/* [IN] - expired packet */
boolean hard
/* [IN] - TRUE if this is a hard timeout (TO- event) */
)
{ /* Body */
PPPFSM_CFG_PTR fsm = fsm_ptr;
PPP_mutex_lock(&fsm->MUTEX);
switch (fsm->STATE) {
case PPP_STATE_CLOSING:
case PPP_STATE_STOPPING:
if (hard) {
/* We've waited for an ack long enough */
fsm->STATE -= 2; /* Stopping/Closing -> Stopped/Closed */
} /* Endif */
break;
case PPP_STATE_REQ_SENT:
case PPP_STATE_ACK_RCVD:
case PPP_STATE_ACK_SENT:
if (hard) {
fsm->STATE = PPP_STATE_STOPPED;
} else if (fsm->STATE == PPP_STATE_ACK_RCVD) {
fsm->STATE = PPP_STATE_REQ_SENT;
} /* Endif */
break;
} /* Endswitch */
PPP_mutex_unlock(&fsm->MUTEX);
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_input
* Returned Value : void
* Comments :
* Called by PPP_rx_task. Parses a xCP packet.
* Side effects :
* Consumes (sends or frees) the packet.
*
*END*-----------------------------------------------------------------*/
void PPPFSM_input
(
PCB_PTR pcb,
/* [IN] - xCP packet */
pointer fsm_data
/* [IN/OUT] - State Machine */
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
PPPFSM_CFG_PTR fsm = fsm_data;
uint_32_ptr stat;
uchar_ptr inp;
uint_16 pcblen, len;
/*
** Parse header (code, id and length).
** If packet is too short, drop it.
*/
stat = NULL;
fsm->PACKET = pcb;
inp = pcb->FRAG[0].FRAGMENT + 2; /* skip the protocol field */
pcblen = pcb->FRAG[0].LENGTH - 2;
PPP_mutex_lock(&fsm->MUTEX);
if (pcblen < CP_HDR_LEN) {
stat = &fsm->ST_CP_SHORT;
} else {
fsm->CODE = *inp++;
fsm->ID = *inp++;
len = *inp++ << 8;
len += *inp++;
if (len < CP_HDR_LEN) {
stat = &fsm->ST_CP_SHORT;
} else if (len > pcblen) {
stat = &fsm->ST_CP_SHORT;
} else if (fsm->STATE < PPP_STATE_CLOSED) {
stat = &fsm->ST_CP_DOWN;
} /* Endif */
} /* Endif */
if (stat) {
PPP_mutex_unlock(&fsm->MUTEX);
++*stat;
PCB_free(pcb);
return;
} /* Endif */
fsm->LENGTH = len - CP_HDR_LEN;
fsm->DATA = inp;
/*
** Action depends on code.
*/
switch (fsm->CODE) {
case CP_CODE_CONF_REQ:
PPPFSM_recvconfreq(fsm, fsm->HANDLE);
break;
case CP_CODE_CONF_ACK:
PPPFSM_recvconfack(fsm);
break;
case CP_CODE_CONF_NAK:
PPPFSM_recvconfnak(fsm, fsm->CALL->recvnak);
break;
case CP_CODE_CONF_REJ:
PPPFSM_recvconfnak(fsm, fsm->CALL->recvrej);
break;
case CP_CODE_TERM_REQ:
PPPFSM_recvtermreq(fsm);
break;
case CP_CODE_TERM_ACK:
PPPFSM_recvtermack(fsm);
break;
case CP_CODE_CODE_REJ:
PPPFSM_recvcoderej(fsm);
break;
default:
if (!fsm->CALL->recvcode || !fsm->CALL->recvcode(fsm)) {
PPPFSM_sendcoderej(fsm);
} /* Endif */
break;
} /* Endswitch */
PPP_mutex_unlock(&fsm->MUTEX);
#else
PCB_free(pcb);
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_buildheader
* Returned Value : void
* Comments :
* Called by PPPFSM_send*. Builds the CP header before sending
* a packet.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_buildheader
(
PPPFSM_CFG_PTR fsm,
/* [IN] - State Machine */
PCB_PTR pcb,
/* [IN] - packet */
uchar code,
/* [IN] - packet code, 0 means use fsm->CODE */
boolean keepid,
/* [IN] - packet id, FALSE mean use fsm->ID */
uint_32 size
/* [IN] - length of packet data */
)
{ /* Body */
uchar_ptr outp = pcb->FRAG[0].FRAGMENT + 2;
if (!code) code = fsm->CODE;
*outp++ = code;
if (!keepid) {
*outp = fsm->CURID;
fsm->CURID = (fsm->CURID + 1) & 0xFF;
} /* Endif */
outp++;
size += CP_HDR_LEN;
*outp++ = (size >> 8) & 0xFF;
*outp++ = size & 0xFF;
pcb->FRAG[0].LENGTH = size + 2;
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_recvconfreq
* Returned Value : void
* Comments :
* Called by PPPFSM_Input. Parses a Configure-Request packet.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends or frees) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_recvconfreq
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
_ppp_handle handle
/* [IN] - the PPP state structure */
)
{ /* Body */
PPP_CFG_PTR ppp_ptr = handle;
uint_32 size;
switch (fsm->STATE) {
case PPP_STATE_CLOSED:
PPPFSM_sendtermack(fsm, FALSE);
return;
case PPP_STATE_CLOSING:
case PPP_STATE_STOPPING:
PCB_free(fsm->PACKET);
return;
case PPP_STATE_OPENED:
/* Go down and restart negotiation */
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendconfreq(fsm, NULL);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
case PPP_STATE_STOPPED:
/* Negotiation started by our peer */
PPPFSM_sendconfreq(fsm, NULL);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
} /* Endswitch */
/*
** Pass the requested configuration options
** to protocol-specific code for checking.
**
** !! Packet consumed here !!
*/
if (fsm->CALL->recvreq) { /* Check CI */
size = fsm->CALL->recvreq(fsm, fsm->NAKS >= _PPP_MAX_CONF_NAKS);
PPPFSM_buildheader(fsm, fsm->PACKET, 0, TRUE, size);
PPP_send_one(ppp_ptr, fsm->CALL->PROTOCOL, fsm->PACKET);
} else if (fsm->LENGTH) {
PPPFSM_sendconfrep(fsm, CP_CODE_CONF_REJ);
} else {
PPPFSM_sendconfrep(fsm, CP_CODE_CONF_ACK);
} /* Endif */
if (fsm->CODE == CP_CODE_CONF_ACK) {
if (fsm->STATE == PPP_STATE_ACK_RCVD) {
/* Inform upper layers */
if (fsm->CALL->linkup) {
if (!fsm->CALL->linkup(fsm)) {
PPPFSM_sendtermreq(fsm, NULL);
fsm->STATE = PPP_STATE_CLOSING;
return;
} /* Endif */
} /* Endif */
fsm->STATE = PPP_STATE_OPENED;
PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
} else {
fsm->STATE = PPP_STATE_ACK_SENT;
} /* Endif */
fsm->NAKS = 0;
} else { /* We sent a NAK or a REJ */
if (fsm->STATE != PPP_STATE_ACK_RCVD) {
fsm->STATE = PPP_STATE_REQ_SENT;
} /* Endif */
if (fsm->CODE == CP_CODE_CONF_NAK ) {
++fsm->NAKS;
} /* Endif */
} /* Endif */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_recvconfack
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Parses a Configure-Ack packet.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends or frees) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_recvconfack
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
/* Verify the packet */
if (fsm->ID != fsm->REQID) {
PCB_free(fsm->PACKET);
return;
} else if (fsm->CALL->recvack) {
if (!fsm->CALL->recvack(fsm)) {
++fsm->ST_CP_BAD_ACK;
PCB_free(fsm->PACKET);
return;
} /* Endif */
} else if (fsm->LENGTH) {
++fsm->ST_CP_BAD_ACK;
PCB_free(fsm->PACKET);
return;
} /* Endif */
/*
** !! Packet consumed here !!
*/
switch (fsm->STATE) {
case PPP_STATE_CLOSED:
case PPP_STATE_STOPPED:
PPPFSM_sendtermack(fsm, FALSE);
break;
case PPP_STATE_REQ_SENT:
/* Restart retransmissions */
fsm->STATE = PPP_STATE_ACK_RCVD;
PCB_free(fsm->PACKET);
PPP_send_restart(fsm->HANDLE, fsm->CALL->PROTOCOL);
break;
case PPP_STATE_ACK_RCVD:
PPPFSM_sendconfreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
case PPP_STATE_ACK_SENT:
/* Inform upper layers */
if (fsm->CALL->linkup) {
if (!fsm->CALL->linkup(fsm)) {
PPPFSM_sendtermreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_CLOSING;
return;
} /* Endif */
} /* Endif */
fsm->STATE = PPP_STATE_OPENED;
PCB_free(fsm->PACKET);
PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
break;
case PPP_STATE_OPENED:
/* Restart negotiation */
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendconfreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
default:
PCB_free(fsm->PACKET);
break;
} /* Endswitch */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_recvconfnak
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Parses a Configure-Nak or
* Configure-Reject packet.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends or frees) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_recvconfnak
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
boolean (_CODE_PTR_ call)(PPPFSM_CFG_PTR)
/* [IN] - Protocol-specific callback for this packet */
)
{ /* Body */
/* Verify the packet */
if (fsm->ID != fsm->REQID) {
PCB_free(fsm->PACKET);
return;
} else if (!call || !call(fsm)) {
if (fsm->CODE == CP_CODE_CONF_NAK) {
++fsm->ST_CP_BAD_NAK;
} else {
++fsm->ST_CP_BAD_REJ;
} /* Endif */
PCB_free(fsm->PACKET);
return;
} /* Endif */
/*
** !! Packet consumed here !!
*/
switch (fsm->STATE) {
case PPP_STATE_CLOSED:
case PPP_STATE_STOPPED:
PPPFSM_sendtermack(fsm, FALSE);
break;
case PPP_STATE_REQ_SENT:
case PPP_STATE_ACK_SENT:
/* They didn't agree -- try another request */
PPPFSM_sendconfreq(fsm, fsm->PACKET);
break;
case PPP_STATE_ACK_RCVD:
PPPFSM_sendconfreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
case PPP_STATE_OPENED:
/* Restart negotiation */
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendconfreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
default:
PCB_free(fsm->PACKET);
break;
} /* Endswitch */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_recvtermreq
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Parses a Terminate-Request packet.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_recvtermreq
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
/*
** !! Packet consumed here !!
*/
switch (fsm->STATE) {
case PPP_STATE_ACK_RCVD:
case PPP_STATE_ACK_SENT:
fsm->STATE = PPP_STATE_REQ_SENT;
PPPFSM_sendtermack(fsm, FALSE);
break;
case PPP_STATE_OPENED:
/* Restart negotiation */
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendtermack(fsm, TRUE);
fsm->STATE = PPP_STATE_STOPPING;
break;
default:
PPPFSM_sendtermack(fsm, FALSE);
break;
} /* Endswitch */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_recvtermack
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Parses a Terminate-Ack packet.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends or frees) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_recvtermack
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
switch (fsm->STATE) {
case PPP_STATE_CLOSING:
case PPP_STATE_STOPPING:
PCB_free(fsm->PACKET);
PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
fsm->STATE -= 2; /* Stopping/Closing -> Stopped/Closed */
break;
case PPP_STATE_ACK_RCVD:
PCB_free(fsm->PACKET);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
case PPP_STATE_OPENED:
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendconfreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_REQ_SENT;
break;
default:
PCB_free(fsm->PACKET);
break;
} /* Endswitch */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_recvcoderej
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Parses a Code-Reject packet.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends or frees) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_recvcoderej
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
if (fsm->LENGTH < CP_HDR_LEN) {
++fsm->ST_CP_SHORT;
PCB_free(fsm->PACKET);
return;
} /* Endif */
/*
** Check if Code-Reject is catastrophic
**
** !! Packet consumed here !!
*/
if (!fsm->CALL->testcode || !fsm->CALL->testcode(fsm)) {
if (fsm->STATE == PPP_STATE_ACK_RCVD) {
fsm->STATE = PPP_STATE_REQ_SENT;
} /* Endif */
PCB_free(fsm->PACKET);
} else {
switch (fsm->STATE) {
case PPP_STATE_CLOSING:
PCB_free(fsm->PACKET);
PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
fsm->STATE = PPP_STATE_CLOSED;
break;
case PPP_STATE_STOPPING:
case PPP_STATE_REQ_SENT:
case PPP_STATE_ACK_RCVD:
case PPP_STATE_ACK_SENT:
PCB_free(fsm->PACKET);
PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
fsm->STATE = PPP_STATE_STOPPED;
break;
case PPP_STATE_OPENED:
if (fsm->CALL->linkdown) {
fsm->CALL->linkdown(fsm);
} /* Endif */
PPPFSM_sendtermreq(fsm, fsm->PACKET);
fsm->STATE = PPP_STATE_STOPPING;
break;
default:
PCB_free(fsm->PACKET);
break;
} /* Endswitch */
} /* Endif */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_sendconfrep
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Builds a 'code' packet from
* the packet in fsm, and sends it.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends) it.
* Sets fsm->CODE to 'code'.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_sendconfrep
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
uint_32 code
/* [IN] - packet code for reply */
)
{ /* Body */
fsm->CODE = fsm->PACKET->FRAG[0].FRAGMENT[2] = code;
PPP_send_one(fsm->HANDLE, fsm->CALL->PROTOCOL, fsm->PACKET);
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_sendtermack
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Builds a Terminate-Ack packet from
* the packet in fsm, and sends it.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_sendtermack
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
boolean delay
/* [IN] - whether or not to Zero-Restart-Counter */
)
{ /* Body */
PPPFSM_buildheader(fsm, fsm->PACKET, CP_CODE_TERM_ACK, TRUE, 0);
if (delay) {
PPP_send_rexmit(fsm->HANDLE, fsm->CALL->PROTOCOL, fsm->PACKET,
1, PPPFSM_timeout, fsm);
} else {
PPP_send_one(fsm->HANDLE, fsm->CALL->PROTOCOL, fsm->PACKET);
} /* Endif */
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_sendcoderej
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Builds a Code-Reject packet from
* the packet in fsm, and sends it.
* Side effects :
* Assumes fsm->PACKET is valid, and consumes (sends) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_sendcoderej
(
PPPFSM_CFG_PTR fsm
/* [IN/OUT] - State Machine */
)
{ /* Body */
PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
uchar_ptr packet, src, dst;
uint_16 length = fsm->PACKET->FRAG[0].LENGTH - 2;
uint_16 size = ppp_ptr->SEND_OPTIONS->MRU - CP_HDR_LEN;
/* Truncate the packet if necessary, so as not to exceed the MTU */
if (length > size) {
length = size;
} /* Endif */
/* Make room for a Code-Reject header */
size = length;
/* Copy the received packet to the data portion of the Code-Reject */
packet = fsm->PACKET->FRAG[0].FRAGMENT + 2;
src = packet + length;
dst = src + CP_HDR_LEN;
while (length--) *--dst = *--src;
/* Build a Code-Reject header */
PPPFSM_buildheader(fsm, fsm->PACKET, CP_CODE_CODE_REJ, FALSE, size);
PPP_send_one(ppp_ptr, fsm->CALL->PROTOCOL, fsm->PACKET);
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_sendconfreq
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Builds a Configure-Request packet
* and sends it.
* Side effects :
* Starts the retransmission timer with the new
* Configure-Request packet.
* If 'packet' is non-NULL, assumes it's valid, and consumes
* (sends) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_sendconfreq
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
PCB_PTR packet
/* [IN] - free packet */
)
{ /* Body */
PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
uchar_ptr outp;
uint_32 size;
if (fsm->STATE <= PPP_STATE_STOPPING || fsm->STATE >= PPP_STATE_OPENED) {
/* Not currently negotiating -- reset options */
if (fsm->CALL->resetreq) {
fsm->CALL->resetreq(fsm);
} /* Endif */
fsm->NAKS = 0;
} /* Endif */
/* Stop the retransmission timer if necessary */
if (fsm->STATE > PPP_STATE_STOPPED && fsm->STATE < PPP_STATE_OPENED) {
PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
} /* Endif */
/* Allocate a packet if necessary */
if (!packet) {
packet = PPP_pcballoc(fsm->CALL->PROTOCOL, ppp_ptr->SEND_OPTIONS->MRU);
if (!packet) {
++fsm->ST_CP_NOBUFS; /* Nonfatal error */
return;
} /* Endif */
} /* Endif */
/* Build the request packet */
outp = packet->FRAG[0].FRAGMENT + 2;
size = packet->FRAG[0].LENGTH - 2 - CP_HDR_LEN;
if (fsm->CALL->buildreq) {
size = fsm->CALL->buildreq(fsm, outp + CP_HDR_LEN, size);
} /* Endif */
fsm->REQID = fsm->CURID;
PPPFSM_buildheader(fsm, packet, CP_CODE_CONF_REQ, FALSE, size);
/* Send the request */
PPP_send_rexmit(ppp_ptr, fsm->CALL->PROTOCOL, packet,
_PPP_MAX_CONF_RETRIES, PPPFSM_timeout, fsm);
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : PPPFSM_sendtermreq
* Returned Value : void
* Comments :
* Called by PPPFSM_input. Builds a Terminate-Request packet from
* the packet in fsm, and sends it.
* Side effects :
* Starts the retransmission timer with the Terminate-Request
* packet.
* If 'packet' is non-NULL, assumes it's valid, and consumes
* (sends) it.
*
*END*-----------------------------------------------------------------*/
#if RTCSCFG_ENABLE_IP4
static void PPPFSM_sendtermreq
(
PPPFSM_CFG_PTR fsm,
/* [IN/OUT] - State Machine */
PCB_PTR packet
/* [IN] - free packet */
)
{ /* Body */
PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
/* Stop the retransmission timer if necessary */
if (fsm->STATE > PPP_STATE_STOPPED && fsm->STATE < PPP_STATE_OPENED) {
PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
} /* Endif */
/* Allocate a packet if necessary */
if (!packet) {
packet = PPP_pcballoc(fsm->CALL->PROTOCOL, CP_HDR_LEN);
if (!packet) {
++fsm->ST_CP_NOBUFS; /* Nonfatal error */
return;
} /* Endif */
} /* Endif */
PPPFSM_buildheader(fsm, packet, CP_CODE_TERM_REQ, FALSE, 0);
PPP_send_rexmit(ppp_ptr, fsm->CALL->PROTOCOL, packet,
_PPP_MAX_TERM_RETRIES, PPPFSM_timeout, fsm);
} /* Endbody */
#endif /* RTCSCFG_ENABLE_IP4 */
/* EOF */