mirror of
https://github.com/dimoniche/solarium.vlad.git
synced 2026-01-30 13:03:30 +03:00
3582 lines
165 KiB
C
3582 lines
165 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* uC/TCP-IP
|
||
* The Embedded TCP/IP Suite
|
||
*
|
||
* (c) Copyright 2003-2007; Micrium, Inc.; Weston, FL
|
||
*
|
||
* All rights reserved. Protected by international copyright laws.
|
||
*
|
||
* uC/TCP-IP is provided in source form for FREE evaluation, for educational
|
||
* use or peaceful research. If you plan on using uC/TCP-IP in a commercial
|
||
* product you need to contact Micrium to properly license its use in your
|
||
* product. We provide ALL the source code for your convenience and to help
|
||
* you experience uC/TCP-IP. The fact that the source code is provided does
|
||
* NOT mean that you can use it without paying a licensing fee.
|
||
*
|
||
* Knowledge of the source code may NOT be used to develop a similar product.
|
||
*
|
||
* Please help us continue to provide the Embedded community with the finest
|
||
* software available. Your honesty is greatly appreciated.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
*
|
||
* NETWORK ICMP LAYER
|
||
* (INTERNET CONTROL MESSAGE PROTOCOL)
|
||
*
|
||
* Filename : net_icmp.c
|
||
* Version : V1.89
|
||
* Programmer(s) : ITJ
|
||
*********************************************************************************************************
|
||
* Note(s) : (1) Supports Internet Control Message Protocol as described in RFC #792 with the following
|
||
* restrictions/constraints :
|
||
*
|
||
* (a) Does NOT support IP forwarding/routing RFC #1122, Section 3.3.1
|
||
*
|
||
* (b) Does NOT support IP multicasting RFC #1122, Section 3.3.7
|
||
*
|
||
* (c) Does NOT support ICMP Address Mask Agent/Server RFC #1122, Section 3.2.2.9
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INCLUDE FILES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#define NET_ICMP_MODULE
|
||
#include <net.h>
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL DEFINES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL CONSTANTS
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL DATA TYPES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL TABLES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL GLOBAL VARIABLES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL FUNCTION PROTOTYPES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/* ------------------- RX FNCTS ------------------- */
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
static void NetICMP_RxPktValidateBuf (NET_BUF_HDR *pbuf_hdr,
|
||
NET_ERR *perr);
|
||
#endif
|
||
|
||
static void NetICMP_RxPktValidate (NET_BUF *pbuf,
|
||
NET_BUF_HDR *pbuf_hdr,
|
||
NET_ICMP_HDR *picmp_hdr,
|
||
NET_ERR *perr);
|
||
|
||
static void NetICMP_RxPktFree (NET_BUF *pbuf);
|
||
|
||
static void NetICMP_RxPktDiscard (NET_BUF *pbuf,
|
||
NET_ERR *perr);
|
||
|
||
|
||
/* ------------------- TX FNCTS ------------------- */
|
||
|
||
static void NetICMP_TxMsgErrValidate (NET_BUF *pbuf,
|
||
NET_BUF_HDR *pbuf_hdr,
|
||
NET_IP_HDR *pip_hdr,
|
||
CPU_INT08U type,
|
||
CPU_INT08U code,
|
||
CPU_INT08U ptr,
|
||
NET_ERR *perr);
|
||
|
||
|
||
static void NetICMP_TxMsgReqValidate (CPU_INT08U type,
|
||
CPU_INT08U code,
|
||
NET_ERR *perr);
|
||
|
||
|
||
static void NetICMP_TxMsgReply (NET_BUF *pbuf,
|
||
NET_BUF_HDR *pbuf_hdr,
|
||
NET_ICMP_HDR *picmp_hdr,
|
||
NET_ERR *perr);
|
||
|
||
|
||
|
||
static void NetICMP_TxPktFree (NET_BUF *pbuf);
|
||
|
||
static void NetICMP_TxPktDiscard (NET_BUF *pbuf,
|
||
NET_ERR *perr);
|
||
|
||
|
||
/* ---------------- HANDLER FNCTS ----------------- */
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuench (NET_BUF *pbuf);
|
||
|
||
static void NetICMP_HandlerTxSrcQuenchClrList(void);
|
||
|
||
static void NetICMP_HandlerTxSrcQuenchClr (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench);
|
||
|
||
static NET_ICMP_TX_SRC_QUENCH *NetICMP_HandlerTxSrcQuenchGet (NET_ERR *perr);
|
||
|
||
static void NetICMP_HandlerTxSrcQuenchFree (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench);
|
||
|
||
static void NetICMP_HandlerTxSrcQuenchRemove (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench);
|
||
|
||
static void NetICMP_HandlerTxSrcQuenchInsert (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench);
|
||
|
||
static void NetICMP_HandlerTxSrcQuenchUnlink (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench);
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchDiscard(NET_ICMP_TX_SRC_QUENCH *ptx_src_quench);
|
||
#endif
|
||
#endif
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL CONFIGURATION ERRORS
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_Init()
|
||
*
|
||
* Description : (1) Initialize Internet Control Message Protocol Layer :
|
||
*
|
||
* (a) Initialize ICMP transmit source quench :
|
||
* (1) Initialize ICMP transmit source quench pool
|
||
* (2) Initialize ICMP transmit source quench table
|
||
* (3) Initialize ICMP transmit source quench list pointers
|
||
*
|
||
* (b) Initialize ICMP statistics & error counters
|
||
*
|
||
*
|
||
* Argument(s) : none.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : Net_Init().
|
||
*
|
||
* This function is an INTERNAL network protocol suite function & MUST NOT be called by
|
||
* application function(s).
|
||
*
|
||
* Note(s) : (2) ICMP transmit source quench pool MUST be initialized PRIOR to initializing the pool
|
||
* with pointers to ICMP transmit source quench entries.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void NetICMP_Init (void)
|
||
{
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
NET_ICMP_TX_SRC_QUENCH *ptx_src_quench_tbl;
|
||
NET_ICMP_SRC_QUENCH_QTY i;
|
||
NET_ERR err;
|
||
|
||
|
||
/* -------- INIT ICMP TX SRC QUENCH POOL/STATS -------- */
|
||
NetICMP_TxSrcQuenchPoolPtr = (NET_ICMP_TX_SRC_QUENCH *)0; /* Init-clr ICMP tx src quench pool (see Note #2). */
|
||
|
||
NetStat_PoolInit((NET_STAT_POOL *)&NetICMP_TxSrcQuenchPoolStat,
|
||
(NET_STAT_POOL_QTY) NET_ICMP_CFG_TX_SRC_QUENCH_SIZE,
|
||
(NET_ERR *)&err);
|
||
|
||
|
||
/* ----------- INIT ICMP TX SRC QUENCH TBL ------------ */
|
||
ptx_src_quench_tbl = &NetICMP_TxSrcQuenchTbl[0];
|
||
for (i = 0; i < NET_ICMP_CFG_TX_SRC_QUENCH_SIZE; i++) {
|
||
/* Init each ICMP tx src quench type--NEVER modify. */
|
||
ptx_src_quench_tbl->Type = NET_ICMP_TYPE_TX_SRC_QUENCH;
|
||
|
||
ptx_src_quench_tbl->Flags = NET_ICMP_FLAG_NONE; /* Init each ICMP tx src quench as NOT used. */
|
||
|
||
#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED)
|
||
NetICMP_HandlerTxSrcQuenchClr(ptx_src_quench_tbl);
|
||
#endif
|
||
/* Free each entry to pool (see Note #2). */
|
||
ptx_src_quench_tbl->NextPtr = (void *)NetICMP_TxSrcQuenchPoolPtr;
|
||
NetICMP_TxSrcQuenchPoolPtr = ptx_src_quench_tbl;
|
||
|
||
ptx_src_quench_tbl++;
|
||
}
|
||
|
||
|
||
/* -------- INIT ICMP TX SRC QUENCH LIST PTRS --------- */
|
||
NetICMP_TxSrcQuenchListHead = (NET_ICMP_TX_SRC_QUENCH *)0;
|
||
NetICMP_TxSrcQuenchListTail = (NET_ICMP_TX_SRC_QUENCH *)0;
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ------------ INIT ICMP STAT & ERR CTRS ------------- */
|
||
NetICMP_TxSeqNbrCtr = 0;
|
||
|
||
|
||
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
|
||
NetICMP_StatRxMsgCtr = 0;
|
||
NetICMP_StatRxMsgProcessedCtr = 0;
|
||
NetICMP_StatRxMsgErrProcessedCtr = 0;
|
||
NetICMP_StatRxMsgReqProcessedCtr = 0;
|
||
NetICMP_StatRxMsgReplyProcessedCtr = 0;
|
||
|
||
NetICMP_StatTxMsgCtr = 0;
|
||
NetICMP_StatTxMsgErrCtr = 0;
|
||
NetICMP_StatTxMsgReqCtr = 0;
|
||
NetICMP_StatTxMsgReplyCtr = 0;
|
||
#endif
|
||
|
||
|
||
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
|
||
NetICMP_ErrRxHdrTypeCtr = 0;
|
||
NetICMP_ErrRxHdrCodeCtr = 0;
|
||
NetICMP_ErrRxHdrMsgLenCtr = 0;
|
||
NetICMP_ErrRxHdrPtrCtr = 0;
|
||
NetICMP_ErrRxHdrChkSumCtr = 0;
|
||
|
||
NetICMP_ErrRxBroadcastCtr = 0;
|
||
|
||
NetICMP_ErrRxPktDiscardedCtr = 0;
|
||
|
||
|
||
NetICMP_ErrTxInvalidLenCtr = 0;
|
||
|
||
NetICMP_ErrTxHdrTypeCtr = 0;
|
||
NetICMP_ErrTxHdrCodeCtr = 0;
|
||
|
||
NetICMP_ErrTxPktDiscardedCtr = 0;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
NetICMP_ErrNullPtrCtr = 0;
|
||
NetICMP_ErrNotUsedCtr = 0;
|
||
|
||
NetICMP_ErrInvalidTypeCtr = 0;
|
||
|
||
|
||
NetICMP_ErrRxInvalidBufIxCtr = 0;
|
||
|
||
NetICMP_ErrRxHdrDataLenCtr = 0;
|
||
|
||
|
||
NetICMP_ErrTxInvalidBufIxCtr = 0;
|
||
|
||
NetICMP_ErrTxHdrPtrCtr = 0;
|
||
#endif
|
||
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
NetICMP_ErrNoneAvailCtr = 0;
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_CfgTxSrcQuenchTh()
|
||
*
|
||
* Description : Configure ICMP transmit source quench entry's access-transmit threshold.
|
||
*
|
||
* Argument(s) : th Desired number of received IP packets from a specific IP source host that trips
|
||
* the transmission of an additional ICMP Source Quench Error Message.
|
||
*
|
||
* Return(s) : DEF_OK, ICMP transmit source quench threshold configured.
|
||
*
|
||
* Caller(s) : Net_InitDflt(),
|
||
* Application.
|
||
*
|
||
* This function is a network protocol suite application interface (API) function & MAY be
|
||
* called by application function(s).
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
CPU_BOOLEAN NetICMP_CfgTxSrcQuenchTh (CPU_INT16U th)
|
||
{
|
||
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
|
||
|
||
#if (NET_ICMP_TX_SRC_QUENCH_TH_MIN > DEF_INT_16U_MIN_VAL)
|
||
if (th < NET_ICMP_TX_SRC_QUENCH_TH_MIN) {
|
||
th = NET_ICMP_TX_SRC_QUENCH_TH_MIN;
|
||
}
|
||
#endif
|
||
#if (NET_ICMP_TX_SRC_QUENCH_TH_MAX < DEF_INT_16U_MAX_VAL)
|
||
if (th > NET_ICMP_TX_SRC_QUENCH_TH_MAX) {
|
||
th = NET_ICMP_TX_SRC_QUENCH_TH_MAX;
|
||
}
|
||
#endif
|
||
|
||
CPU_CRITICAL_ENTER();
|
||
NetICMP_TxSrcQuenchTxTh_nbr = th;
|
||
CPU_CRITICAL_EXIT();
|
||
|
||
return (DEF_OK);
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_Rx()
|
||
*
|
||
* Description : (1) Process received messages :
|
||
*
|
||
* (a) Validate ICMP packet
|
||
* (b) Demultiplex ICMP message
|
||
* (c) Free ICMP packet
|
||
* (d) Update receive statistics
|
||
*
|
||
* (2) Although ICMP data units are typically referred to as 'messages' (see RFC #792, Section
|
||
* 'Introduction'), the term 'ICMP packet' (see RFC #1983, 'packet') is used for ICMP
|
||
* Receive until the packet is validated as an ICMP message.
|
||
*
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer that received ICMP packet.
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE ICMP message successfully received & processed.
|
||
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
|
||
*
|
||
* ---- RETURNED BY NetICMP_RxPktDiscard() : -----
|
||
* NET_ERR_RX Receive error; packet discarded.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetIP_RxPktDemuxDatagram().
|
||
*
|
||
* This function is an INTERNAL network protocol suite function & MUST NOT be called by
|
||
* application function(s).
|
||
*
|
||
* Note(s) : (3) NetICMP_Rx() blocked until network initialization completes.
|
||
*
|
||
* (4) #### ICMP Receive Error/Reply Messages NOT yet implemented :
|
||
*
|
||
* (a) Define "User Process" to report ICMP Error Messages to Transport &/or Application Layers.
|
||
*
|
||
* (b) Define procedure to demultiplex & enqueue ICMP Reply Messages to Application.
|
||
*
|
||
* (1) MUST implement mechanism to de-queue ICMP message data from single, complete
|
||
* datagram packet buffers or multiple, fragmented packet buffers.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
void NetICMP_Rx (NET_BUF *pbuf,
|
||
NET_ERR *perr)
|
||
{
|
||
#if ((((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \
|
||
(NET_CTR_CFG_ERR_EN == DEF_ENABLED)) || \
|
||
(NET_CTR_CFG_STAT_EN == DEF_ENABLED)) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
|
||
NET_CTR *pctr;
|
||
#endif
|
||
NET_BUF_HDR *pbuf_hdr;
|
||
NET_ICMP_HDR *picmp_hdr;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
||
if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit rx (see Note #3). */
|
||
*perr = NET_ERR_INIT_INCOMPLETE;
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE PTR ------------------- */
|
||
if (pbuf == (NET_BUF *)0) {
|
||
NetICMP_RxPktDiscard(pbuf, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrNullPtrCtr);
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
|
||
NET_CTR_STAT_INC(NetICMP_StatRxMsgCtr);
|
||
|
||
|
||
/* ----------------- VALIDATE ICMP PKT ---------------- */
|
||
pbuf_hdr = &pbuf->Hdr;
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
NetICMP_RxPktValidateBuf(pbuf_hdr, perr); /* Validate rx'd buf. */
|
||
switch (*perr) {
|
||
case NET_ICMP_ERR_NONE:
|
||
break;
|
||
|
||
|
||
case NET_ERR_INVALID_PROTOCOL:
|
||
case NET_BUF_ERR_INVALID_IX:
|
||
default:
|
||
NetICMP_RxPktDiscard(pbuf, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
#endif
|
||
picmp_hdr = (NET_ICMP_HDR *)&pbuf->Data[pbuf_hdr->ICMP_MsgIx];
|
||
NetICMP_RxPktValidate(pbuf, pbuf_hdr, picmp_hdr, perr); /* Validate rx'd pkt. */
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ------------------ DEMUX ICMP MSG ------------------ */
|
||
switch (*perr) {
|
||
case NET_ICMP_ERR_MSG_TYPE_ERR:
|
||
/* See Note #4a. */
|
||
|
||
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
|
||
pctr = &NetICMP_StatRxMsgErrProcessedCtr;
|
||
#endif
|
||
break;
|
||
|
||
|
||
case NET_ICMP_ERR_MSG_TYPE_REQ:
|
||
NetICMP_TxMsgReply(pbuf, pbuf_hdr, picmp_hdr, perr);
|
||
|
||
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
|
||
pctr = &NetICMP_StatRxMsgReqProcessedCtr;
|
||
#endif
|
||
break;
|
||
|
||
|
||
case NET_ICMP_ERR_MSG_TYPE_REPLY:
|
||
/* See Note #4b. */
|
||
|
||
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
|
||
pctr = &NetICMP_StatRxMsgReplyProcessedCtr;
|
||
#endif
|
||
break;
|
||
|
||
|
||
case NET_ICMP_ERR_INVALID_TYPE:
|
||
case NET_ICMP_ERR_INVALID_CODE:
|
||
case NET_ICMP_ERR_INVALID_PTR:
|
||
case NET_ICMP_ERR_INVALID_LEN:
|
||
case NET_ICMP_ERR_INVALID_LEN_DATA:
|
||
case NET_ICMP_ERR_INVALID_CHK_SUM:
|
||
default:
|
||
NetICMP_RxPktDiscard(pbuf, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
/* --------- FREE ICMP PKT / UPDATE RX STATS ---------- */
|
||
switch (*perr) { /* Chk err from NetICMP_TxMsg???(). */
|
||
case NET_ICMP_ERR_NONE:
|
||
NetICMP_RxPktFree(pbuf);
|
||
NET_CTR_STAT_INC(NetICMP_StatRxMsgProcessedCtr);
|
||
NET_CTR_STAT_INC(*pctr);
|
||
break;
|
||
|
||
|
||
default:
|
||
NetICMP_RxPktDiscard(pbuf, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxMsgErr()
|
||
*
|
||
* Description : (1) Transmit ICMP Error Message in response to received packet with one or more errors :
|
||
*
|
||
* (a) Validate ICMP Error Message
|
||
*
|
||
* (b) Get buffer for ICMP Error Message :
|
||
*
|
||
* (1) Calculate ICMP Error Message buffer size
|
||
* (2) Copy received packet's IP header & data into ICMP Error Message
|
||
* (3) Initialize ICMP Error Message buffer controls
|
||
*
|
||
* (c) Prepare ICMP Error Message :
|
||
*
|
||
* (1) Type See Note #1cA
|
||
* (2) Code See Note #1cA
|
||
* (3) Pointer
|
||
* (4) Unused
|
||
* (5) Check-Sum
|
||
*
|
||
* (A) See 'net_icmp.h ICMP MESSAGE TYPES & CODES Notes #2 & #3' for supported
|
||
* ICMP message types & codes.
|
||
*
|
||
* (d) Transmit ICMP Error Message
|
||
*
|
||
* (1) RFC #1122, Section 3.2.2 specifies that "an ICMP error message SHOULD be sent
|
||
* with normal (i.e., zero) TOS bits". RFC #1349, Section 5.1 confirms that "an
|
||
* ICMP error message is always sent with the default TOS (0000)".
|
||
*
|
||
* (e) Free ICMP Error Message buffer
|
||
*
|
||
* (f) Update transmit statistics
|
||
*
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer that received a packet with error(s).
|
||
*
|
||
* type ICMP Error Message type (see Note #1cA) :
|
||
*
|
||
* NET_ICMP_MSG_TYPE_DEST_UNREACH
|
||
* NET_ICMP_MSG_TYPE_SRC_QUENCH
|
||
* NET_ICMP_MSG_TYPE_TIME_EXCEED
|
||
* NET_ICMP_MSG_TYPE_PARAM_PROB
|
||
*
|
||
* code ICMP Error Message code (see Note #1cA).
|
||
*
|
||
* ptr Pointer to received packet's ICMP error (optional).
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE ICMP Error Message successfully transmitted.
|
||
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
|
||
*
|
||
* --- RETURNED BY NetICMP_TxPktDiscard() : ---
|
||
* NET_ERR_TX Transmit error; packet discarded.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : various.
|
||
*
|
||
* This function is an INTERNAL network protocol suite function & MUST NOT be called by
|
||
* application function(s).
|
||
*
|
||
* Note(s) : (2) NetICMP_TxMsgErr() blocked until network initialization completes.
|
||
*
|
||
* (3) (a) The following IP header fields MUST be decoded &/or converted from network-order to host-
|
||
* order BEFORE any ICMP Error Messages are transmitted (see 'net_ip.c NetIP_RxPktValidate()
|
||
* Note #3') :
|
||
*
|
||
* (1) Header Length
|
||
* (2) Total Length
|
||
* (3) Source Address
|
||
* (4) Destination Address
|
||
*
|
||
* (b) The following IP header fields were NOT previously decoded &/or converted from network-
|
||
* order to host-order & are NOT available :
|
||
*
|
||
* (1) IP Data Length
|
||
*
|
||
* (4) Default case already invalidated in NetICMP_TxMsgErrValidate(). However, the default
|
||
* case is included as an extra precaution in case 'type' is incorrectly modified.
|
||
*
|
||
* (5) Assumes network buffer's protocol header size is large enough to accomodate ICMP header
|
||
* size (see 'net_buf.h NETWORK BUFFER INDEX & SIZE DEFINES Note #1').
|
||
*$PAGE*
|
||
* (6) Some buffer controls were previously initialized in NetBuf_Get() when the buffer
|
||
* was allocated earlier in this function. These buffer controls do NOT need to be
|
||
* re-initialized but are shown for completeness.
|
||
*
|
||
* (7) (a) ICMP message Check-Sum MUST be calculated AFTER the entire ICMP message has been
|
||
* prepared. In addition, ALL multi-octet words are converted from host-order to
|
||
* network-order since "the sum of 16-bit integers can be computed in either byte
|
||
* order" [RFC #1071, Section 2.(B)].
|
||
*
|
||
* (b) ICMP message Check-Sum field MUST be cleared to '0' BEFORE the ICMP message Check-Sum
|
||
* is calculated (see RFC #792, Sections 'Destination Unreachable Message : Checksum',
|
||
* 'Time Exceeded Message : Checksum', 'Source Quench Message : Checksum', & 'Parameter
|
||
* Problem Message : Checksum').
|
||
*
|
||
* (c) The ICMP message Check-Sum field is returned in network-order & MUST NOT be re-converted
|
||
* back to host-order (see 'net_util.c NetUtil_16BitOnesCplChkSumHdrCalc() Note #3b').
|
||
*
|
||
* (8) Network buffer already freed by lower layer; only increment error counter.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void NetICMP_TxMsgErr (NET_BUF *pbuf,
|
||
CPU_INT08U type,
|
||
CPU_INT08U code,
|
||
CPU_INT08U ptr,
|
||
NET_ERR *perr)
|
||
{
|
||
#if (((NET_CTR_CFG_STAT_EN == DEF_ENABLED) || \
|
||
(NET_CTR_CFG_ERR_EN == DEF_ENABLED)) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
NET_BUF_HDR *pbuf_hdr;
|
||
NET_IP_HDR *pip_hdr;
|
||
NET_BUF *pmsg_err;
|
||
NET_BUF_HDR *pmsg_err_hdr;
|
||
NET_ICMP_HDR_ERR *picmp_hdr_err;
|
||
NET_ICMP_HDR_PARAM_PROB *picmp_hdr_param_prob;
|
||
CPU_INT16U msg_size_hdr;
|
||
CPU_INT16U msg_size_data_ip;
|
||
CPU_INT16U msg_size_data;
|
||
CPU_INT16U msg_size_tot;
|
||
CPU_INT16U msg_ix;
|
||
CPU_INT16U msg_ix_data;
|
||
CPU_INT16U msg_chk_sum;
|
||
NET_ERR err;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
||
if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit tx (see Note #2). */
|
||
*perr = NET_ERR_INIT_INCOMPLETE;
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE PTR ------------------- */
|
||
if (pbuf == (NET_BUF *)0) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrNullPtrCtr);
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
/* ------------- VALIDATE ICMP TX ERR MSG ------------- */
|
||
pbuf_hdr = &pbuf->Hdr;
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (pbuf_hdr->IP_HdrIx == NET_BUF_IX_NONE) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxInvalidBufIxCtr);
|
||
return;
|
||
}
|
||
#endif
|
||
pip_hdr = (NET_IP_HDR *)&pbuf->Data[pbuf_hdr->IP_HdrIx];
|
||
|
||
|
||
NetICMP_TxMsgErrValidate(pbuf, pbuf_hdr, pip_hdr, type, code, ptr, &err);
|
||
|
||
if (err != NET_ICMP_ERR_NONE) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/* --------------- GET ICMP ERR MSG BUF --------------- */
|
||
/* Calc err msg buf size. */
|
||
switch (type) {
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_DEST_UNREACH;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_SRC_QUENCH;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_TIME_EXCEED;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_PARAM_PROB;
|
||
break;
|
||
|
||
|
||
default: /* See Note #4. */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
if (pbuf_hdr->IP_TotLen >= pbuf_hdr->IP_HdrLen) { /* If IP tot len > IP hdr len & ... */
|
||
msg_size_data_ip = pbuf_hdr->IP_TotLen - pbuf_hdr->IP_HdrLen; /* Calc IP data len (see Note #3b1). */
|
||
if (msg_size_data_ip >= NET_ICMP_MSG_ERR_DATA_SIZE_MIN_OCTETS) { /* ... ip data >= min ICMP data len, ... */
|
||
/* ... get max ICMP err msg len. */
|
||
msg_size_data = pbuf_hdr->IP_HdrLen + NET_ICMP_MSG_ERR_DATA_SIZE_MIN_OCTETS;
|
||
} else { /* Else get max IP tot len. */
|
||
msg_size_data = pbuf_hdr->IP_TotLen;
|
||
}
|
||
} else { /* Else get max IP tot len. */
|
||
msg_size_data = pbuf_hdr->IP_TotLen;
|
||
}
|
||
|
||
msg_size_tot = msg_size_hdr + msg_size_data;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (NET_BUF_DATA_TX_IX < msg_size_hdr) { /* See Note #5. */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxInvalidBufIxCtr);
|
||
return;
|
||
}
|
||
#endif
|
||
msg_ix = NET_BUF_DATA_TX_IX - msg_size_hdr;
|
||
|
||
|
||
pmsg_err = NetBuf_Get((NET_BUF_SIZE) msg_size_tot, /* Get err msg buf. */
|
||
(NET_BUF_SIZE) msg_ix,
|
||
(CPU_INT16U ) NET_BUF_FLAG_NONE,
|
||
(NET_ERR *)&err);
|
||
if (err != NET_BUF_ERR_NONE) {
|
||
NetICMP_TxPktDiscard(pmsg_err, perr);
|
||
return;
|
||
}
|
||
|
||
|
||
msg_ix_data = msg_ix + msg_size_hdr;
|
||
NetBuf_DataWr((NET_BUF *) pmsg_err, /* Copy rx'd IP hdr & data into ICMP err tx buf. */
|
||
(NET_BUF_SIZE) msg_ix_data,
|
||
(NET_BUF_SIZE) msg_size_data,
|
||
(CPU_INT08U *) pip_hdr,
|
||
(NET_ERR *)&err);
|
||
if (err != NET_BUF_ERR_NONE) {
|
||
NetICMP_TxPktDiscard(pmsg_err, perr);
|
||
return;
|
||
}
|
||
|
||
/* Init err msg buf ctrls. */
|
||
pmsg_err_hdr = &pmsg_err->Hdr;
|
||
pmsg_err_hdr->ICMP_MsgIx = (CPU_INT16U )msg_ix;
|
||
pmsg_err_hdr->ICMP_MsgLen = (CPU_INT16U )msg_size_tot;
|
||
pmsg_err_hdr->ICMP_HdrLen = (CPU_INT16U )msg_size_hdr;
|
||
pmsg_err_hdr->TotLen = (NET_BUF_SIZE)pmsg_err_hdr->ICMP_MsgLen;
|
||
pmsg_err_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_ICMP;
|
||
#if 0 /* Init'd in NetBuf_Get() [see Note #6]. */
|
||
pmsg_err_hdr->DataIx = NET_BUF_IX_NONE;
|
||
pmsg_err_hdr->DataLen = 0;
|
||
#endif
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* --------------- PREPARE ICMP ERR MSG --------------- */
|
||
switch (type) {
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
picmp_hdr_err = (NET_ICMP_HDR_ERR *)&pmsg_err->Data[pmsg_err_hdr->ICMP_MsgIx];
|
||
picmp_hdr_err->Type = type;
|
||
picmp_hdr_err->Code = code;
|
||
/* Clr unused octets. */
|
||
Mem_Clr((void *)picmp_hdr_err->Unused,
|
||
(CPU_SIZE_T)NET_ICMP_HDR_NBR_OCTETS_UNUSED);
|
||
/* Calc ICMP msg chk sum (see Note #7). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_err->ChkSum, 0x0000); /* Clr chk sum (see Note #7b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *) picmp_hdr_err,
|
||
(CPU_INT16U) pmsg_err_hdr->ICMP_MsgLen,
|
||
(NET_ERR *)&err);
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_err->ChkSum, &msg_chk_sum); /* Copy chk sum in net order (see Note #7c).*/
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
picmp_hdr_param_prob = (NET_ICMP_HDR_PARAM_PROB *)&pmsg_err->Data[pmsg_err_hdr->ICMP_MsgIx];
|
||
picmp_hdr_param_prob->Type = type;
|
||
picmp_hdr_param_prob->Code = code;
|
||
picmp_hdr_param_prob->Ptr = ptr;
|
||
/* Clr unused octets. */
|
||
Mem_Clr((void *)picmp_hdr_param_prob->Unused,
|
||
(CPU_SIZE_T)NET_ICMP_HDR_NBR_OCTETS_UNUSED_PARAM_PROB);
|
||
/* Calc ICMP msg chk sum (see Note #7). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_param_prob->ChkSum, 0x0000);/* Clr chk sum (see Note #7b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *) picmp_hdr_param_prob,
|
||
(CPU_INT16U) pmsg_err_hdr->ICMP_MsgLen,
|
||
(NET_ERR *)&err);
|
||
/* Copy chk sum in net order (see Note #7c).*/
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_param_prob->ChkSum, &msg_chk_sum);
|
||
break;
|
||
|
||
|
||
default: /* See Note #4. */
|
||
NetICMP_TxPktDiscard(pmsg_err, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
if (err != NET_UTIL_ERR_NONE) { /* Chk err from NetUtil_16BitOnesCplChkSumHdrCalc(). */
|
||
NetICMP_TxPktDiscard(pmsg_err, perr);
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
/* ----------------- TX ICMP ERR MSG ------------------ */
|
||
NetIP_Tx((NET_BUF *)pmsg_err,
|
||
(NET_IP_ADDR)pbuf_hdr->IP_AddrDest,
|
||
(NET_IP_ADDR)pbuf_hdr->IP_AddrSrc,
|
||
(NET_IP_TOS )NET_IP_TOS_DFLT, /* See Note #1da. */
|
||
(NET_IP_TTL )NET_IP_TTL_DFLT,
|
||
(CPU_INT16U )NET_IP_FLAG_NONE,
|
||
(void *)0,
|
||
(NET_ERR *)perr);
|
||
|
||
|
||
|
||
/* ------- FREE ICMP ERR MSG / UPDATE TX STATS -------- */
|
||
switch (*perr) {
|
||
case NET_IP_ERR_NONE:
|
||
NetICMP_TxPktFree(pmsg_err);
|
||
NET_CTR_STAT_INC(NetICMP_StatTxMsgCtr);
|
||
NET_CTR_STAT_INC(NetICMP_StatTxMsgErrCtr);
|
||
break;
|
||
|
||
|
||
case NET_ERR_TX:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxPktDiscardedCtr); /* See Note #8. */
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
|
||
|
||
case NET_ERR_INIT_INCOMPLETE:
|
||
default:
|
||
NetICMP_TxPktDiscard(pmsg_err, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxMsgReq()
|
||
*
|
||
* Description : (1) Transmit ICMP Request Message :
|
||
*
|
||
* (a) Validate ICMP Request Message :
|
||
*
|
||
* (1) Validate the following arguments :
|
||
*
|
||
* (A) Type
|
||
* (B) Code
|
||
*
|
||
* (2) Validation of the following arguments deferred to NetIP_Tx() :
|
||
*
|
||
* (A) Type of Service (TOS) See RFC #1349, Section 5.1
|
||
* (B) Time-to-Live (TTL)
|
||
* (C) Destination Address
|
||
* (D) IP flags
|
||
* (E) IP options
|
||
*
|
||
* (3) Validation ignores the following arguments :
|
||
*
|
||
* (A) Data
|
||
* (B) Data length
|
||
*
|
||
* (b) Get buffer for ICMP Request Message :
|
||
*
|
||
* (1) Calculate ICMP Request Message buffer size
|
||
* (2) Copy data into ICMP Request Message
|
||
* (3) Initialize ICMP Request Message buffer controls
|
||
*
|
||
* (c) Prepare ICMP Request Message :
|
||
*
|
||
* (1) Type See Note #1cA
|
||
* (2) Code See Note #1cA
|
||
* (3) Identification (ID)
|
||
* (4) Sequence Number
|
||
* (5) Data
|
||
* (6) Timestamps
|
||
*
|
||
* (A) See 'net_icmp.h ICMP MESSAGE TYPES & CODES Notes #2 & #3' for supported ICMP
|
||
* message types & codes.
|
||
*
|
||
* (B) Timestamp Request Message
|
||
*
|
||
* (1) "The Originate Timestamp is the time the sender last touched the message
|
||
* before sending it" (RFC #792, Section 'Timestamp or Timestamp Reply Message :
|
||
* Description').
|
||
*
|
||
* (d) Transmit ICMP Request Message
|
||
*
|
||
* (e) Free ICMP Request Message buffer
|
||
*
|
||
* (f) Update transmit statistics
|
||
*
|
||
* (g) Return ICMP Request Message Identification & Sequence Number
|
||
* OR
|
||
* NULL id & sequence number structure, on failure
|
||
*
|
||
*
|
||
*$PAGE*
|
||
* Argument(s) : type ICMP Request Message type (see Note #1cA) :
|
||
*
|
||
* NET_ICMP_MSG_TYPE_ECHO_REQ
|
||
* NET_ICMP_MSG_TYPE_TS_REQ
|
||
* NET_ICMP_MSG_TYPE_ADDR_MASK_REQ
|
||
*
|
||
* code ICMP Request Message code (see Note #1cA).
|
||
*
|
||
* id ICMP Request Message id (see 'net_os.c NetOS_ICMP_TxMsgReq() Note #3b').
|
||
*
|
||
* TOS Specific TOS to transmit IP packet
|
||
* (see 'net_ip.h IP HEADER TYPE OF SERVICE (TOS) DEFINES').
|
||
*
|
||
* TTL Specific TTL to transmit IP packet (see 'net_ip.h IP HEADER DEFINES').
|
||
*
|
||
* addr_dest Destination IP address.
|
||
*
|
||
* flags Flags to select transmit options; bit-field flags logically OR'd :
|
||
*
|
||
* NET_IP_FLAG_NONE No IP transmit flags selected.
|
||
* NET_IP_FLAG_TX_DONT_FRAG Set IP 'Don't Frag' flag.
|
||
*
|
||
* popts Pointer to one or more IP options configuration data structures :
|
||
*
|
||
* NULL NO IP transmit options configuration.
|
||
* NET_IP_OPT_CFG_ROUTE_TS Route &/or Internet Timestamp options configuration.
|
||
* NET_IP_OPT_CFG_SECURITY Security options configuration
|
||
* (see 'net_ip.h Note #1f').
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE ICMP Request Message successfully transmitted.
|
||
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
|
||
*
|
||
* ---- RETURNED BY NetICMP_TxPktDiscard() : ----
|
||
* NET_ERR_TX Transmit error; packet discarded.
|
||
*
|
||
* Return(s) : ICMP Request Message's Identification (ID) & Sequence Numbers, if NO errors.
|
||
*
|
||
* NULL Identification (ID) & Sequence Numbers, otherwise.
|
||
*
|
||
* Caller(s) : NetOS_ICMP_TxMsgReq().
|
||
*
|
||
* This function is an INTERNAL network protocol suite function & SHOULD NOT be called by
|
||
* application function(s).
|
||
*
|
||
* Note(s) : (2) NetICMP_TxMsgReq() blocked until network initialization completes.
|
||
*
|
||
* (3) NetICMP_TxMsgReq() is the internal ICMP handler for ICMP Request Messages. Its
|
||
* global declaration is required since NetOS_ICMP_TxMsgReq() calls the handler function
|
||
* from the OS port file (see also 'net_os.c NetOS_ICMP_TxMsgReq() Note #1').
|
||
*
|
||
* (4) Default case already invalidated in NetICMP_TxMsgReqValidate(). However, the default
|
||
* case is included as an extra precaution in case 'type' is incorrectly modified.
|
||
*
|
||
* (5) Assumes network buffer's protocol header size is large enough to accomodate ICMP header
|
||
* size (see 'net_buf.h NETWORK BUFFER INDEX & SIZE DEFINES Note #1').
|
||
*
|
||
* (6) Some buffer controls were previously initialized in NetBuf_Get() when the buffer
|
||
* was allocated earlier in this function. These buffer controls do NOT need to be
|
||
* re-initialized but are shown for completeness.
|
||
*
|
||
* (7) (a) ICMP message Check-Sum MUST be calculated AFTER the entire ICMP message has been
|
||
* prepared. In addition, ALL multi-octet words are converted from host-order to
|
||
* network-order since "the sum of 16-bit integers can be computed in either byte
|
||
* order" [RFC #1071, Section 2.(B)].
|
||
*
|
||
* (b) ICMP message Check-Sum field MUST be cleared to '0' BEFORE the ICMP message
|
||
* Check-Sum is calculated (see RFC #792, Sections 'Echo or Echo Reply Message :
|
||
* Checksum', 'Timestamp or Timestamp Reply Message : Checksum'; & RFC #950,
|
||
* Appendix I 'Address Mask ICMP', Section 'ICMP Fields : Checksum').
|
||
*
|
||
* (c) The ICMP message Check-Sum field is returned in network-order & MUST NOT be re-
|
||
* converted back to host-order (see 'net_util.c NetUtil_16BitOnesCplChkSumHdrCalc()
|
||
* Note #3b' & 'net_util.c NetUtil_16BitOnesCplChkSumDataCalc() Note #4b').
|
||
*
|
||
* (8) Network buffer already freed by lower layer; only increment error counter.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
NET_ICMP_REQ_ID_SEQ NetICMP_TxMsgReq (CPU_INT08U type,
|
||
CPU_INT08U code,
|
||
CPU_INT16U id,
|
||
NET_IP_TOS TOS,
|
||
NET_IP_TTL TTL,
|
||
NET_IP_ADDR addr_dest,
|
||
CPU_INT16U flags,
|
||
void *popts,
|
||
void *p_data,
|
||
CPU_INT16U data_len,
|
||
NET_ERR *perr)
|
||
{
|
||
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
NET_ICMP_REQ_ID_SEQ id_seq;
|
||
CPU_INT16U msg_size_hdr;
|
||
CPU_INT16U msg_size_data;
|
||
CPU_INT16U msg_size_tot;
|
||
CPU_INT16U msg_seq_nbr;
|
||
CPU_INT16U msg_ix;
|
||
CPU_INT16U msg_ix_data;
|
||
CPU_INT16U msg_chk_sum;
|
||
NET_TS ts;
|
||
NET_BUF *pmsg_req;
|
||
NET_BUF_HDR *pmsg_req_hdr;
|
||
NET_ICMP_HDR_ECHO *picmp_hdr_echo;
|
||
NET_ICMP_HDR_TS *picmp_hdr_ts;
|
||
NET_ICMP_HDR_ADDR_MASK *picmp_hdr_addr;
|
||
NET_ERR err;
|
||
|
||
/* Prepare err rtn val. */
|
||
id_seq.ID = 0;
|
||
id_seq.SeqNbr = 0;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
||
if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit tx (see Note #2). */
|
||
*perr = NET_ERR_INIT_INCOMPLETE;
|
||
return (id_seq);
|
||
}
|
||
#endif
|
||
|
||
|
||
/* ------------- VALIDATE ICMP TX REQ MSG ------------- */
|
||
NetICMP_TxMsgReqValidate(type, code, &err);
|
||
|
||
if (err != NET_ICMP_ERR_NONE) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return (id_seq);
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/* --------------- GET ICMP REQ MSG BUF --------------- */
|
||
/* Calc req msg buf size. */
|
||
switch (type) {
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_ECHO;
|
||
|
||
if (p_data != (void *)0) {
|
||
msg_size_data = data_len;
|
||
} else {
|
||
msg_size_data = 0;
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
#if 1 /* ???? Rtn err OR ignore data? */
|
||
if (p_data != (void *)0) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return (id_seq);
|
||
}
|
||
if (data_len > 0) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return (id_seq);
|
||
}
|
||
#endif
|
||
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_TS;
|
||
msg_size_data = 0;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REQ:
|
||
#if 1 /* ???? Rtn err OR ignore data? */
|
||
if (p_data != (void *)0) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return (id_seq);
|
||
}
|
||
if (data_len > 0) {
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return (id_seq);
|
||
}
|
||
#endif
|
||
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_ADDR_MASK;
|
||
msg_size_data = 0;
|
||
break;
|
||
|
||
|
||
default: /* See Note #4. */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return (id_seq); /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
msg_size_tot = msg_size_hdr + msg_size_data;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (NET_BUF_DATA_TX_IX < msg_size_hdr) { /* See Note #5. */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxInvalidBufIxCtr);
|
||
return (id_seq);
|
||
}
|
||
#endif
|
||
msg_ix = NET_BUF_DATA_TX_IX - msg_size_hdr;
|
||
|
||
|
||
pmsg_req = NetBuf_Get((NET_BUF_SIZE) msg_size_tot, /* Get req msg buf. */
|
||
(NET_BUF_SIZE) msg_ix,
|
||
(CPU_INT16U ) NET_BUF_FLAG_NONE,
|
||
(NET_ERR *)&err);
|
||
if (err != NET_BUF_ERR_NONE) {
|
||
NetICMP_TxPktDiscard(pmsg_req, perr);
|
||
return (id_seq);
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/* Init req msg buf ctrls. */
|
||
pmsg_req_hdr = &pmsg_req->Hdr;
|
||
pmsg_req_hdr->ICMP_MsgIx = (CPU_INT16U )msg_ix;
|
||
pmsg_req_hdr->ICMP_MsgLen = (CPU_INT16U )msg_size_tot;
|
||
pmsg_req_hdr->ICMP_HdrLen = (CPU_INT16U )msg_size_hdr;
|
||
pmsg_req_hdr->TotLen = (NET_BUF_SIZE)pmsg_req_hdr->ICMP_MsgLen;
|
||
pmsg_req_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_ICMP;
|
||
msg_ix_data = msg_ix + msg_size_hdr;
|
||
|
||
|
||
if (msg_size_data > 0) { /* Copy data into ICMP req tx buf. */
|
||
NetBuf_DataWr((NET_BUF *) pmsg_req,
|
||
(NET_BUF_SIZE) msg_ix_data,
|
||
(NET_BUF_SIZE) msg_size_data,
|
||
(CPU_INT08U *) p_data,
|
||
(NET_ERR *)&err);
|
||
if (err != NET_BUF_ERR_NONE) {
|
||
NetICMP_TxPktDiscard(pmsg_req, perr);
|
||
return (id_seq);
|
||
}
|
||
|
||
pmsg_req_hdr->DataIx = (CPU_INT16U )msg_ix_data;
|
||
pmsg_req_hdr->DataLen = (NET_BUF_SIZE)msg_size_data;
|
||
#if 0 /* Init'd in NetBuf_Get() [see Note #6]. */
|
||
} else {
|
||
pmsg_req_hdr->DataIx = NET_BUF_IX_NONE;
|
||
pmsg_req_hdr->DataLen = 0;
|
||
#endif
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/* --------------- PREPARE ICMP REQ MSG --------------- */
|
||
NET_ICMP_TX_GET_SEQ_NBR(msg_seq_nbr);
|
||
|
||
switch (type) {
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
picmp_hdr_echo = (NET_ICMP_HDR_ECHO *)&pmsg_req->Data[pmsg_req_hdr->ICMP_MsgIx];
|
||
picmp_hdr_echo->Type = NET_ICMP_MSG_TYPE_ECHO_REQ;
|
||
picmp_hdr_echo->Code = NET_ICMP_MSG_CODE_ECHO_REQ;
|
||
NET_UTIL_VAL_COPY_SET_NET_16(&picmp_hdr_echo->ID, &id);
|
||
NET_UTIL_VAL_COPY_SET_NET_16(&picmp_hdr_echo->SeqNbr, &msg_seq_nbr);
|
||
/* Calc ICMP msg chk sum (see Note #7). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_echo->ChkSum, 0x0000); /* Clr chk sum (see Note #7b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumDataCalc((void *) pmsg_req,
|
||
(void *) 0,
|
||
(CPU_INT16U) 0,
|
||
(NET_ERR *)&err);
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_echo->ChkSum, &msg_chk_sum); /* Copy chk sum in net order (see Note #7c).*/
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
picmp_hdr_ts = (NET_ICMP_HDR_TS *)&pmsg_req->Data[pmsg_req_hdr->ICMP_MsgIx];
|
||
picmp_hdr_ts->Type = NET_ICMP_MSG_TYPE_TS_REQ;
|
||
picmp_hdr_ts->Code = NET_ICMP_MSG_CODE_TS_REQ;
|
||
ts = NetUtil_TS_Get(); /* See Note #1cB1. */
|
||
NET_UTIL_VAL_COPY_SET_NET_16(&picmp_hdr_ts->ID, &id);
|
||
NET_UTIL_VAL_COPY_SET_NET_16(&picmp_hdr_ts->SeqNbr, &msg_seq_nbr);
|
||
NET_UTIL_VAL_COPY_SET_NET_32(&picmp_hdr_ts->TS_Originate, &ts);
|
||
NET_UTIL_VAL_SET_NET_32(&picmp_hdr_ts->TS_Rx, NET_TS_NONE);
|
||
NET_UTIL_VAL_SET_NET_32(&picmp_hdr_ts->TS_Tx, NET_TS_NONE);
|
||
/* Calc ICMP msg chk sum (see Note #7). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_ts->ChkSum, 0x0000); /* Clr chk sum (see Note #7b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *) picmp_hdr_ts,
|
||
(CPU_INT16U) pmsg_req_hdr->ICMP_MsgLen,
|
||
(NET_ERR *)&err);
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_ts->ChkSum, &msg_chk_sum); /* Copy chk sum in net order (see Note #7c).*/
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REQ:
|
||
picmp_hdr_addr = (NET_ICMP_HDR_ADDR_MASK *)&pmsg_req->Data[pmsg_req_hdr->ICMP_MsgIx];
|
||
picmp_hdr_addr->Type = NET_ICMP_MSG_TYPE_ADDR_MASK_REQ;
|
||
picmp_hdr_addr->Code = NET_ICMP_MSG_CODE_ADDR_MASK_REQ;
|
||
NET_UTIL_VAL_COPY_SET_NET_16(&picmp_hdr_addr->ID, &id);
|
||
NET_UTIL_VAL_COPY_SET_NET_16(&picmp_hdr_addr->SeqNbr, &msg_seq_nbr);
|
||
NET_UTIL_VAL_SET_NET_32(&picmp_hdr_addr->AddrMask, NET_IP_ADDR_NONE);
|
||
/* Calc ICMP msg chk sum (see Note #7). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_addr->ChkSum, 0x0000); /* Clr chk sum (see Note #7b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *) picmp_hdr_addr,
|
||
(CPU_INT16U) pmsg_req_hdr->ICMP_MsgLen,
|
||
(NET_ERR *)&err);
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_addr->ChkSum, &msg_chk_sum); /* Copy chk sum in net order (see Note #7c).*/
|
||
break;
|
||
|
||
|
||
default: /* See Note #4. */
|
||
NetICMP_TxPktDiscard(pmsg_req, perr);
|
||
return (id_seq); /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
if (err != NET_UTIL_ERR_NONE) { /* Chk err from NetUtil_16BitOnesCplChkSum()'s. */
|
||
NetICMP_TxPktDiscard(pmsg_req, perr);
|
||
return (id_seq);
|
||
}
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ----------------- TX ICMP REQ MSG ------------------ */
|
||
NetIP_Tx((NET_BUF *)pmsg_req,
|
||
(NET_IP_ADDR)NetIP_AddrThisHost,
|
||
(NET_IP_ADDR)addr_dest,
|
||
(NET_IP_TOS )TOS,
|
||
(NET_IP_TTL )TTL,
|
||
(CPU_INT16U )flags,
|
||
(void *)popts,
|
||
(NET_ERR *)perr);
|
||
|
||
|
||
|
||
/* ------- FREE ICMP REQ MSG / UPDATE TX STATS -------- */
|
||
switch (*perr) {
|
||
case NET_IP_ERR_NONE:
|
||
NetICMP_TxPktFree(pmsg_req);
|
||
NET_CTR_STAT_INC(NetICMP_StatTxMsgCtr);
|
||
NET_CTR_STAT_INC(NetICMP_StatTxMsgReqCtr);
|
||
break;
|
||
|
||
|
||
case NET_ERR_TX:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxPktDiscardedCtr); /* See Note #8. */
|
||
return (id_seq); /* Prevent 'break NOT reachable' compiler warning. */
|
||
|
||
|
||
case NET_ERR_INIT_INCOMPLETE:
|
||
default:
|
||
NetICMP_TxPktDiscard(pmsg_req, perr);
|
||
return (id_seq); /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
|
||
/* ----------- RTN ICMP REQ MSG ID/SEQ NBR ------------ */
|
||
id_seq.ID = id;
|
||
id_seq.SeqNbr = msg_seq_nbr;
|
||
|
||
return (id_seq);
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerRx()
|
||
*
|
||
* Description : Handle & reply to incoming IP packets for ICMP error &/or status conditions.
|
||
*
|
||
* (1) (a) When network low-resources status is set, transmit ICMP Source Quench Error Messages.
|
||
*
|
||
* (b) When network low-resources status clears, clear the ICMP Transmit Source Quench List.
|
||
*
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer that received an IP packet.
|
||
* ---- Argument validated in NetIP_RxPktValidate()
|
||
* by NetIP_Rx().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetIP_RxPktValidate().
|
||
*
|
||
* This function is an INTERNAL network protocol suite function & MUST NOT be called by
|
||
* application function(s).
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void NetICMP_HandlerRx (NET_BUF *pbuf)
|
||
{
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
NET_DBG_STATUS rsrc_lo;
|
||
|
||
|
||
rsrc_lo = NetDbg_MonTaskStatGetHandlerLo(); /* Get lo rsrc's status. */
|
||
|
||
if (rsrc_lo != NET_DBG_STATUS_OK) { /* If net rsrc's lo, ... */
|
||
NetICMP_HandlerTxSrcQuench(pbuf); /* ... tx ICMP src quench err to IP pkt src host. */
|
||
|
||
} else { /* Else if ICMP tx src quench list avail, ... */
|
||
if (NetICMP_TxSrcQuenchListHead != (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
NetICMP_HandlerTxSrcQuenchClrList(); /* ... clr tx src quench list. */
|
||
}
|
||
}
|
||
|
||
#else
|
||
(void)&pbuf; /* Prevent compiler warning. */
|
||
#endif
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
*********************************************************************************************************
|
||
* LOCAL FUNCTIONS
|
||
*********************************************************************************************************
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_RxPktValidateBuf()
|
||
*
|
||
* Description : Validate received buffer header as ICMP protocol.
|
||
*
|
||
* Argument(s) : pbuf_hdr Pointer to network buffer header that received ICMP packet.
|
||
* -------- Argument validated in NetICMP_Rx().
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE Received buffer's ICMP header validated.
|
||
* NET_ERR_INVALID_PROTOCOL Buffer's protocol type is NOT ICMP.
|
||
* NET_BUF_ERR_INVALID_IX Invalid buffer index.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_Rx().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
static void NetICMP_RxPktValidateBuf (NET_BUF_HDR *pbuf_hdr,
|
||
NET_ERR *perr)
|
||
{
|
||
#if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
|
||
/* --------------- VALIDATE ICMP BUF HDR -------------- */
|
||
if (pbuf_hdr->ProtocolHdrType != NET_PROTOCOL_TYPE_ICMP) {
|
||
NET_CTR_ERR_INC(Net_ErrInvalidProtocolCtr);
|
||
*perr = NET_ERR_INVALID_PROTOCOL;
|
||
return;
|
||
}
|
||
|
||
if (pbuf_hdr->ICMP_MsgIx == NET_BUF_IX_NONE) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxInvalidBufIxCtr);
|
||
*perr = NET_BUF_ERR_INVALID_IX;
|
||
return;
|
||
}
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_RxPktValidate()
|
||
*
|
||
* Description : (1) Validate received ICMP packet :
|
||
*
|
||
* (a) Validate the received packet's destination (see Note #3).
|
||
*
|
||
* (b) (1) Validate the received packet's following ICMP message fields :
|
||
*
|
||
* (A) Type
|
||
* (B) Code
|
||
* (C) Message Length
|
||
* (D) Pointer See RFC #792, Section 'Parameter Problem Message'
|
||
* (E) Check-Sum See Note #7a
|
||
*
|
||
* (2) Validation ignores the following ICMP header fields :
|
||
*
|
||
* (A) Unused See RFC # 792, Section 'Message Formats'
|
||
* (B) Data See RFC #1122, Sections 3.2.2 & 3.2.2.6
|
||
* (C) Identification (ID) See RFC # 792, Sections 'Echo or Echo Reply Message'
|
||
* & 'Timestamp or Timestamp Reply Message'
|
||
* (D) Sequence Number See RFC # 792, Sections 'Echo or Echo Reply Message'
|
||
* & 'Timestamp or Timestamp Reply Message'
|
||
*
|
||
* (c) Convert the following ICMP message fields from network-order to host-order :
|
||
*
|
||
* (1) Check-Sum See Note #7c
|
||
*
|
||
* (A) These fields are NOT converted directly in the received packet buffer's
|
||
* data area but are converted in local or network buffer variables ONLY.
|
||
*
|
||
* (d) Update network buffer's length controls.
|
||
*
|
||
* (e) Demultiplex ICMP message type.
|
||
*
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer that received ICMP packet.
|
||
* ---- Argument checked in NetICMP_Rx().
|
||
*
|
||
* pbuf_hdr Pointer to network buffer header.
|
||
* -------- Argument validated in NetICMP_Rx().
|
||
*
|
||
* picmp_hdr Pointer to received packet's ICMP header.
|
||
* --------- Argument validated in NetICMP_Rx()/NetICMP_RxPktValidateBuf().
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_MSG_TYPE_ERR Received packet validated as ICMP Error Message.
|
||
* NET_ICMP_ERR_MSG_TYPE_REQ Received packet validated as ICMP Request Message.
|
||
* NET_ICMP_ERR_MSG_TYPE_REPLY Received packet validated as ICMP Reply Message.
|
||
*
|
||
* NET_ICMP_ERR_RX_BROADCAST Packet received via broadcast.
|
||
*
|
||
* NET_ICMP_ERR_INVALID_TYPE Invalid/unknown ICMP message type.
|
||
* NET_ICMP_ERR_INVALID_CODE Invalid/unknown ICMP message code.
|
||
* NET_ICMP_ERR_INVALID_PTR Invalid ICMP message pointer outside ICMP message.
|
||
* NET_ICMP_ERR_INVALID_LEN Invalid ICMP message length.
|
||
* NET_ICMP_ERR_INVALID_LEN_DATA Invalid ICMP message data length.
|
||
* NET_ICMP_ERR_INVALID_CHK_SUM Invalid ICMP check-sum.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_Rx().
|
||
*
|
||
* Note(s) : (2) See 'net_icmp.h ICMP HEADER' for ICMP header format.
|
||
*
|
||
* (3) (a) RFC #1122, Sections 3.2.2.6 & 3.2.2.8 state that "an ICMP ... Request destined to an
|
||
* IP broadcast ... address MAY be silently discarded".
|
||
*
|
||
* However, NO RFC specifies how OTHER ICMP messages should handle messages received by
|
||
* broadcast. ???? Therefore, it is assumed that ALL ICMP messages destined to an IP
|
||
* broadcast address SHOULD be silently discarded.
|
||
*
|
||
* (b) Since a packet destined to a valid IP broadcast address MUST also have been received as
|
||
* a link-layer broadcast (see RFC #1122, Section 3.3.6 & 'net_ip.c NetIP_RxPktValidate()
|
||
* Note #9d3B'), the determination of an IP broadcast destination address need only verify
|
||
* that the received packet was received as a link-layer broadcast packet.
|
||
*
|
||
* (4) (a) RFC #1122, Section 3.2.2 requires that ICMP messages with the following invalid ICMP
|
||
* header fields be "silently discarded" :
|
||
*
|
||
* (1) Type RFC #1122, Section 3.2.2
|
||
*
|
||
* (b) Assumes that ICMP messages with the following invalid ICMP header fields should also
|
||
* be "silently discarded" :
|
||
*
|
||
* (1) Code
|
||
* (2) Message Length
|
||
* (3) Pointer
|
||
* (4) Check-Sum
|
||
*$PAGE*
|
||
* (5) See 'net_icmp.h ICMP MESSAGE TYPES & CODES Notes #2 & #3' for currently unsupported
|
||
* ICMP message types/codes.
|
||
*
|
||
* (6) Since ICMP message headers do NOT contain a message length field, the ICMP Message Length
|
||
* is assumed to be the remaining IP Datagram Length.
|
||
*
|
||
* (7) (a) ICMP message Check-Sum field MUST be validated AFTER (or BEFORE) any multi-octet
|
||
* words are converted from network-order to host-order since "the sum of 16-bit
|
||
* integers can be computed in either byte order" [RFC #1071, Section 2.(B)].
|
||
*
|
||
* In other words, the ICMP message Check-Sum CANNOT be validated AFTER SOME but NOT
|
||
* ALL multi-octet words have been converted from network-order to host-order.
|
||
*
|
||
* However, ALL received packets' multi-octet words are converted in local or network
|
||
* buffer variables ONLY (see Note #1cA). Therefore, ICMP message Check-Sum may be
|
||
* validated at any point.
|
||
*
|
||
* (b) RFC #792, Section 'Echo or Echo Reply Message : Checksum' specifies that "if the
|
||
* total length is odd, the received data is padded with one octet of zeros for
|
||
* computing the checksum".
|
||
*
|
||
* However, NO RFC specifies how OTHER ICMP message types should handle odd-length
|
||
* check-sums. Therefore, it is assumed that ICMP Echo Request & Echo Reply Messages
|
||
* should handle odd-length check-sums according to RFC #792's 'Echo or Echo Reply
|
||
* Message : Checksum' specification, while ALL other ICMP message types should handle
|
||
* odd-length check-sums according to RFC #1071, Section 4.1.
|
||
*
|
||
* See also 'net_util.c NetUtil_16BitSumDataCalc() Note #8'.
|
||
*
|
||
* (c) After the ICMP message Check-Sum is validated, it is NOT necessary to convert the
|
||
* Check-Sum from network-order to host-order since it is NOT required for further
|
||
* processing.
|
||
*
|
||
* (8) Default case already invalidated earlier in this function. However, the default case
|
||
* is included as an extra precaution in case 'Type' is incorrectly modified.
|
||
*
|
||
* (9) (a) (1) Except for ICMP Echo & Echo Reply Messages (see Note #9b), most ICMP messages do
|
||
* NOT permit user &/or application data (see RFC #792 & RFC #1122, Sections 3.2.2).
|
||
*
|
||
* (2) Most ICMP messages that do NOT contain user &/or application data will NOT be
|
||
* received in separate packet buffers since most ICMP messages are NOT large enough
|
||
* to be fragmented since the minimum network buffer size MUST be configured such
|
||
* that most ICMP messages fit within a single packet buffer (see 'net_buf.h
|
||
* NETWORK BUFFER INDEX & SIZE DEFINES Note #1d').
|
||
*
|
||
* However, RFC #1122, Section 3.2.2 states that "every ICMP error message includes
|
||
* the Internet header and at least the first 8 data octets of the datagram that
|
||
* triggered the error; more than 8 octets MAY be sent". Thus, it is possible that
|
||
* some received ICMP error messages MAY contain more than 8 octets of the Internet
|
||
* header & may therefore be received in one or more fragmented packet buffers.
|
||
*
|
||
* Furthermore, these additional error message octets SHOULD NOT contain user &/or
|
||
* application data.
|
||
*
|
||
* (3) ICMP data index value to clear was previously initialized in NetBuf_Get() when
|
||
* the buffer was allocated. This index value does NOT need to be re-cleared but
|
||
* is shown for completeness.
|
||
*
|
||
* (b) (1) ICMP Echo & Echo Reply Messages permit the transmission & receipt of user &/or
|
||
* application data (see RFC #792, Section 'Echo or Echo Reply Message' & RFC #1122,
|
||
* Section 3.2.2.6).
|
||
*
|
||
* Since the minimum network buffer size MUST be configured such that the entire
|
||
* ICMP Echo Message header MUST be received in a single packet (see 'net_buf.h
|
||
* NETWORK BUFFER INDEX & SIZE DEFINES Note #1d'), after the ICMP Echo Message
|
||
* header size is decremented from the first packet buffer's remaining number of
|
||
* data octets, any remaining octets MUST be user &/or application data octets.
|
||
*
|
||
* (A) Note that the 'Data' index is updated regardless of a null-size data length.
|
||
*
|
||
* (2) If additional packet buffers exist, the remaining IP datagram 'Data' MUST be
|
||
* user &/or application data. Therefore, the 'Data' length does NOT need to
|
||
* be adjusted but the 'Data' index MUST be updated.
|
||
*
|
||
* (c) #### Total ICMP Message Length is duplicated in ALL fragmented packet buffers
|
||
* (may NOT be necessary; remove if unnecessary).
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
static void NetICMP_RxPktValidate (NET_BUF *pbuf,
|
||
NET_BUF_HDR *pbuf_hdr,
|
||
NET_ICMP_HDR *picmp_hdr,
|
||
NET_ERR *perr)
|
||
{
|
||
#if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
CPU_BOOLEAN rx_broadcast;
|
||
CPU_BOOLEAN icmp_chk_sum_valid;
|
||
CPU_INT16U icmp_msg_len_hdr;
|
||
CPU_INT16U icmp_msg_len_min;
|
||
CPU_INT16U icmp_msg_len_max;
|
||
CPU_INT16U icmp_msg_len;
|
||
NET_ICMP_HDR_PARAM_PROB *picmp_param_prob;
|
||
NET_BUF *pbuf_next;
|
||
NET_BUF_HDR *pbuf_next_hdr;
|
||
|
||
|
||
/* -------------- VALIDATE ICMP RX DEST --------------- */
|
||
rx_broadcast = DEF_BIT_IS_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_RX);
|
||
if (rx_broadcast != DEF_NO) { /* If ICMP rx'd as broadcast, rtn err (see Note #3). */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxBroadcastCtr);
|
||
*perr = NET_ICMP_ERR_RX_BROADCAST;
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
/* ------------- VALIDATE ICMP TYPE/CODE -------------- */
|
||
switch (picmp_hdr->Type) { /* See Notes #4a1 & #4b1. */
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_DEST_NET:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST:
|
||
case NET_ICMP_MSG_CODE_DEST_PROTOCOL:
|
||
case NET_ICMP_MSG_CODE_DEST_PORT:
|
||
case NET_ICMP_MSG_CODE_DEST_FRAG_NEEDED:
|
||
case NET_ICMP_MSG_CODE_DEST_ROUTE_FAIL:
|
||
case NET_ICMP_MSG_CODE_DEST_NET_UNKNOWN:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST_UNKNOWN:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST_ISOLATED:
|
||
case NET_ICMP_MSG_CODE_DEST_NET_TOS:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST_TOS:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_DEST_UNREACH;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_DEST_UNREACH;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_DEST_UNREACH;
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_SRC_QUENCH:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_SRC_QUENCH;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_SRC_QUENCH;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_SRC_QUENCH;
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
/*$PAGE*/
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_TIME_EXCEED_TTL:
|
||
case NET_ICMP_MSG_CODE_TIME_EXCEED_FRAG_REASM:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_TIME_EXCEED;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_TIME_EXCEED;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_TIME_EXCEED;
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR:
|
||
case NET_ICMP_MSG_CODE_PARAM_PROB_OPT_MISSING:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_PARAM_PROB;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_PARAM_PROB;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_PARAM_PROB;
|
||
|
||
picmp_param_prob = (NET_ICMP_HDR_PARAM_PROB *)picmp_hdr;
|
||
if (picmp_param_prob->Ptr < NET_ICMP_MSG_PTR_MIN_PARAM_PROB) { /* If ptr val < min ptr val, .. */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrPtrCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_PTR; /* ... rtn err (see Note #4b3). */
|
||
return;
|
||
}
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
case NET_ICMP_MSG_TYPE_ECHO_REPLY:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_ECHO:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_ECHO;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_ECHO;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_ECHO;
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
case NET_ICMP_MSG_TYPE_TS_REPLY:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_TS:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_TS;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_TS;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_TS;
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
/*$PAGE*/
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REPLY:
|
||
switch (picmp_hdr->Code) {
|
||
case NET_ICMP_MSG_CODE_ADDR_MASK:
|
||
icmp_msg_len_hdr = NET_ICMP_HDR_SIZE_ADDR_MASK;
|
||
icmp_msg_len_min = NET_ICMP_MSG_LEN_MIN_ADDR_MASK;
|
||
icmp_msg_len_max = NET_ICMP_MSG_LEN_MAX_ADDR_MASK;
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
#if 0 /* ---------------- UNSUPPORTED TYPES ----------------- */
|
||
/* See Note #5. */
|
||
case NET_ICMP_MSG_TYPE_REDIRECT:
|
||
case NET_ICMP_MSG_TYPE_ROUTE_REQ:
|
||
case NET_ICMP_MSG_TYPE_ROUTE_AD:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REQ:
|
||
/* 'break' intentionally omitted; do NOT move from the */
|
||
/* ... following case : 'default'. */
|
||
#endif
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* -------------- VALIDATE ICMP MSG LEN --------------- */
|
||
icmp_msg_len = pbuf_hdr->IP_DatagramLen; /* See Note #6. */
|
||
pbuf_hdr->ICMP_MsgLen = icmp_msg_len;
|
||
if (pbuf_hdr->ICMP_MsgLen < icmp_msg_len_min) { /* If msg len < min msg len, rtn err. */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrMsgLenCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_LEN;
|
||
return;
|
||
}
|
||
if (icmp_msg_len_max != NET_ICMP_MSG_LEN_MAX_NONE) {
|
||
if (pbuf_hdr->ICMP_MsgLen > icmp_msg_len_max) { /* If msg len > max msg len, rtn err. */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrMsgLenCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_LEN;
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (picmp_hdr->Type == NET_ICMP_MSG_TYPE_PARAM_PROB) { /* For ICMP Param Prob msg, ... */
|
||
if (picmp_param_prob->Ptr >= pbuf_hdr->ICMP_MsgLen) { /* ... if ptr val >= msg len, ... */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrPtrCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_PTR; /* ... rtn err (see Note #4b3). */
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
/* -------------- VALIDATE ICMP CHK SUM --------------- */
|
||
/* See Note #7. */
|
||
switch (picmp_hdr->Type) { /* See Note #7b. */
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
case NET_ICMP_MSG_TYPE_TS_REPLY:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REPLY:
|
||
icmp_chk_sum_valid = NetUtil_16BitOnesCplChkSumHdrVerify((void *)picmp_hdr,
|
||
(CPU_INT16U)pbuf_hdr->ICMP_MsgLen,
|
||
(NET_ERR *)perr);
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
case NET_ICMP_MSG_TYPE_ECHO_REPLY:
|
||
icmp_chk_sum_valid = NetUtil_16BitOnesCplChkSumDataVerify((void *)pbuf,
|
||
(void *)0,
|
||
(CPU_INT16U)0,
|
||
(NET_ERR *)perr);
|
||
break;
|
||
|
||
|
||
default: /* See Note #8. */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
if (icmp_chk_sum_valid != DEF_OK) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrChkSumCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CHK_SUM;
|
||
return;
|
||
}
|
||
#if 0 /* Conv to host-order NOT necessary (see Note #7c). */
|
||
(void)NET_UTIL_VAL_GET_NET_16(&picmp_hdr->ChkSum);
|
||
#endif
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ----------------- UPDATE BUF CTRLS ----------------- */
|
||
pbuf_hdr->ICMP_HdrLen = icmp_msg_len_hdr;
|
||
|
||
switch (picmp_hdr->Type) {
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
case NET_ICMP_MSG_TYPE_TS_REPLY:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REPLY:
|
||
pbuf_hdr->DataLen = 0; /* Clr data len/ix (see Note #9a1). */
|
||
#if 0 /* Clr'd in NetBuf_Get() [see Note #9a3]. */
|
||
pbuf_hdr->DataIx = NET_BUF_IX_NONE;
|
||
#endif
|
||
|
||
pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr;
|
||
while (pbuf_next != (NET_BUF *)0) { /* Clr ALL pkt bufs' data len/ix (see Note #9a2). */
|
||
pbuf_next_hdr = &pbuf_next->Hdr;
|
||
pbuf_next_hdr->DataLen = 0;
|
||
#if 0 /* Clr'd in NetBuf_Get() [see Note #9a3]. */
|
||
pbuf_next_hdr->DataIx = NET_BUF_IX_NONE;
|
||
#endif
|
||
pbuf_next_hdr->ICMP_HdrLen = 0; /* NULL ICMP hdr len in each pkt buf. */
|
||
pbuf_next_hdr->ICMP_MsgLen = icmp_msg_len; /* Dup ICMP msg len in each pkt buf (see Note #9c). */
|
||
pbuf_next = (NET_BUF *)pbuf_next_hdr->NextBufPtr;
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
case NET_ICMP_MSG_TYPE_ECHO_REPLY:
|
||
/* Calc ICMP Echo Msg data len/ix (see Note #9b). */
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (pbuf_hdr->ICMP_HdrLen > pbuf_hdr->DataLen) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrDataLenCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_LEN_DATA;
|
||
return;
|
||
}
|
||
#endif
|
||
pbuf_hdr->DataLen -= (NET_BUF_SIZE) pbuf_hdr->ICMP_HdrLen;
|
||
pbuf_hdr->DataIx = (CPU_INT16U )(pbuf_hdr->ICMP_MsgIx + NET_ICMP_MSG_LEN_MIN_ECHO);
|
||
|
||
pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr;
|
||
while (pbuf_next != (NET_BUF *)0) { /* Calc ALL pkt bufs' data len/ix (see Note #9b2). */
|
||
pbuf_next_hdr = &pbuf_next->Hdr;
|
||
pbuf_next_hdr->DataIx = pbuf_next_hdr->ICMP_MsgIx;
|
||
pbuf_next_hdr->ICMP_HdrLen = 0; /* NULL ICMP hdr len in each pkt buf. */
|
||
pbuf_next_hdr->ICMP_MsgLen = icmp_msg_len; /* Dup ICMP msg len in each pkt buf (see Note #9c). */
|
||
pbuf_next = (NET_BUF *)pbuf_next_hdr->NextBufPtr;
|
||
}
|
||
break;
|
||
|
||
|
||
default: /* See Note #8. */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
|
||
/* --------------- DEMUX ICMP MSG TYPE ---------------- */
|
||
switch (picmp_hdr->Type) {
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
*perr = NET_ICMP_ERR_MSG_TYPE_ERR;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
*perr = NET_ICMP_ERR_MSG_TYPE_REQ;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REPLY:
|
||
case NET_ICMP_MSG_TYPE_TS_REPLY:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REPLY:
|
||
*perr = NET_ICMP_ERR_MSG_TYPE_REPLY;
|
||
break;
|
||
|
||
|
||
default: /* See Note #8. */
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxHdrTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_RxPktFree()
|
||
*
|
||
* Description : Free network buffer(s).
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_Rx().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void NetICMP_RxPktFree (NET_BUF *pbuf)
|
||
{
|
||
NetBuf_FreeBufList((NET_BUF *)pbuf,
|
||
(NET_CTR *)0);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_RxPktDiscard()
|
||
*
|
||
* Description : On any ICMP Receive errors, discard ICMP packet(s) & buffer(s).
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer.
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ERR_RX Receive error; packet discarded.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_Rx().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void NetICMP_RxPktDiscard (NET_BUF *pbuf,
|
||
NET_ERR *perr)
|
||
{
|
||
NET_CTR *pctr;
|
||
|
||
|
||
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
|
||
pctr = (NET_CTR *)&NetICMP_ErrRxPktDiscardedCtr;
|
||
#else
|
||
pctr = (NET_CTR *) 0;
|
||
#endif
|
||
NetBuf_FreeBufList((NET_BUF *)pbuf,
|
||
(NET_CTR *)pctr);
|
||
|
||
*perr = NET_ERR_RX;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxMsgErrValidate()
|
||
*
|
||
* Description : (1) Validate received packet & transmit error parameters for ICMP Error Message transmit :
|
||
*
|
||
* (a) RFC #1122, Section 3.2.2 specifies that "an ICMP error message MUST NOT be sent as
|
||
* the result of receiving" :
|
||
*
|
||
* (1) "An ICMP Error Message", ...
|
||
*
|
||
* (2) "A datagram destined to an IP broadcast or IP multicast address", ...
|
||
*
|
||
* (A) Any packet received as an IP broadcast or IP multicast destination address MUST
|
||
* also have been received as a link-layer broadcast (see RFC #1122, Section 3.3.6
|
||
* & 'net_ip.c NetIP_RxPktValidate() Note #9d3').
|
||
*
|
||
* Therefore, it is NOT necessary to re-validate the IP destination address as a
|
||
* non-broadcast address since it has ALREADY been validated as a non-broadcast
|
||
* at the link-layer (see Note #1a1).
|
||
*
|
||
* (B) See also 'net_ip.h Note #1d'.
|
||
*
|
||
* (3) "A datagram sent as a link-layer broadcast", ...
|
||
*
|
||
* (4) "A non-initial fragment", ...
|
||
*
|
||
* (5) "A datagram whose source address does not define a single host -- e.g., a zero address,
|
||
* a loopback address, a broadcast address, a multicast address, or a Class E address"
|
||
*
|
||
* (A) ALL IP source addresses already validated (see 'net_ip.c NetIP_RxPktValidate()
|
||
* Note #9c') except 'This Host' & 'Specified Host' addresses.
|
||
*
|
||
* (B) See also 'net_ip.h Note #1d'.
|
||
*
|
||
* (b) Validate ICMP Error Message transmit parameters :
|
||
*
|
||
* (1) Type
|
||
* (2) Code
|
||
* (3) Pointer See Note #6
|
||
*
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer that received a packet with error(s).
|
||
* ---- Argument checked in NetICMP_TxMsgErr().
|
||
*
|
||
* pbuf_hdr Pointer to network buffer header.
|
||
* -------- Argument validated in NetICMP_TxMsgErr().
|
||
*
|
||
* pip_hdr Pointer to received packet's IP header.
|
||
* ------- Argument validated in NetICMP_TxMsgErr().
|
||
*
|
||
* type ICMP Error Message type (see Note #5) :
|
||
*
|
||
* NET_ICMP_MSG_TYPE_DEST_UNREACH
|
||
* NET_ICMP_MSG_TYPE_SRC_QUENCH
|
||
* NET_ICMP_MSG_TYPE_TIME_EXCEED
|
||
* NET_ICMP_MSG_TYPE_PARAM_PROB
|
||
*
|
||
* code ICMP Error Message code (see Note #5).
|
||
*
|
||
* ptr Pointer to received packet's ICMP error (optional).
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE Received packet successfully validated
|
||
* for ICMP transmit error message.
|
||
* NET_ICMP_ERR_TX_INVALID_BROADCAST Packet received as a broadcast packet.
|
||
* NET_ICMP_ERR_TX_INVALID_ADDR_SRC Packet received with a non-single host
|
||
* IP source address.
|
||
* NET_ICMP_ERR_TX_INVALID_FRAG Packet received as a non-initial fragment.
|
||
* NET_ICMP_ERR_TX_INVALID_ERR_MSG Packet received as an ICMP Error Message.
|
||
* NET_ICMP_ERR_INVALID_TYPE Invalid/unknown ICMP message type.
|
||
* NET_ICMP_ERR_INVALID_CODE Invalid/unknown ICMP message code.
|
||
* NET_ICMP_ERR_INVALID_PTR Invalid message pointer outside error message.
|
||
* NET_BUF_ERR_INVALID_IX Invalid buffer index.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_TxMsgErr().
|
||
*$PAGE*
|
||
* Note(s) : (2) The following IP header fields MUST be converted from network-order to host-order BEFORE
|
||
* any transmit ICMP Error Messages are validated :
|
||
*
|
||
* (a) Total Length See 'net_ip.c NetIP_RxPktValidate() Note #3b'
|
||
* (b) Source Address See 'net_ip.c NetIP_RxPktValidate() Note #3c'
|
||
*
|
||
* (3) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
|
||
*
|
||
* (4) Default case already invalidated in NetIP_RxPktValidate(). However, the default case
|
||
* is included as an extra precaution in case 'IP_AddrSrc' is incorrectly modified.
|
||
*
|
||
* (5) See 'net_icmp.h ICMP MESSAGE TYPES & CODES Notes #2 & #3' for supported ICMP message
|
||
* types & codes.
|
||
*
|
||
* (6) (a) ICMP Parameter Problem Messages' pointer fields validated by comparing the pointer
|
||
* field value to minimum & maximum pointer field values.
|
||
*
|
||
* (b) Since an ICMP Parameter Problem Message's minimum pointer field value is NOT less
|
||
* than zero (see 'net_icmp.h ICMP POINTER DEFINES'), a minimum pointer field value
|
||
* check is NOT required unless native data type 'CPU_INT16U' is incorrectly configured
|
||
* as a signed integer in 'cpu.h'.
|
||
*
|
||
* (c) Since an ICMP Parameter Problem Message may be received for an IP or higher-layer
|
||
* protocol, the maximum pointer field value is specific to each received ICMP packets'
|
||
* IP header length & demultiplexed protocol header length :
|
||
*
|
||
* Pointer Field Value < Maximum Pointer Field Value = IP Header Length
|
||
* [ + Other Protocol Header Length ]
|
||
*
|
||
* (d) See 'net_icmp.h ICMP POINTER DEFINES Note #2' for supported ICMP Parameter Problem
|
||
* Message protocols.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
static void NetICMP_TxMsgErrValidate (NET_BUF *pbuf,
|
||
NET_BUF_HDR *pbuf_hdr,
|
||
NET_IP_HDR *pip_hdr,
|
||
CPU_INT08U type,
|
||
CPU_INT08U code,
|
||
CPU_INT08U ptr,
|
||
NET_ERR *perr)
|
||
{
|
||
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \
|
||
(NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
CPU_INT16U ptr_max;
|
||
CPU_INT16U ptr_max_protocol;
|
||
#endif
|
||
CPU_BOOLEAN rx_broadcast;
|
||
CPU_BOOLEAN ip_flag_frags_more;
|
||
CPU_INT16U ip_flags;
|
||
CPU_INT16U ip_frag_offset;
|
||
NET_ICMP_HDR *picmp_hdr;
|
||
|
||
|
||
|
||
/* ------------- CHK LINK-LAYER BROADCAST ------------- */
|
||
rx_broadcast = DEF_BIT_IS_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_RX);
|
||
if (rx_broadcast != DEF_NO) { /* If pkt rx'd via broadcast, ... */
|
||
*perr = NET_ICMP_ERR_TX_INVALID_BROADCAST; /* ... rtn err (see Note #1a3). */
|
||
return;
|
||
}
|
||
|
||
|
||
/* ----------------- CHK IP DEST ADDR ----------------- */
|
||
/* See Note #1a2. */
|
||
/* Dest addr already validated (see Note #1a2A). */
|
||
|
||
|
||
/* ----------------- CHK IP SRC ADDR ------------------ */
|
||
/* See Note #1a5. */
|
||
if (pbuf_hdr->IP_AddrSrc == NET_IP_ADDR_THIS_HOST) { /* Chk invalid 'This Host' (see Note #1a3A). */
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ADDR_SRC;
|
||
return;
|
||
}
|
||
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
|
||
/* Chk invalid Class-A specified host (see Note #1a5A). */
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
|
||
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ADDR_SRC;
|
||
return;
|
||
}
|
||
|
||
} else if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
|
||
/* Chk invalid Class-B specified host (see Note #1a5A). */
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
|
||
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ADDR_SRC;
|
||
return;
|
||
}
|
||
|
||
} else if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
|
||
/* Chk invalid Class-C specified host (see Note #1a5A). */
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
|
||
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ADDR_SRC;
|
||
return;
|
||
}
|
||
|
||
} else { /* Discard invalid addr class (see Notes #3 & #4). */
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ADDR_SRC;
|
||
return;
|
||
}
|
||
|
||
|
||
/* ------------------- CHK IP FRAG -------------------- */
|
||
|
||
ip_flags = pbuf_hdr->IP_Flags_FragOffset & NET_IP_HDR_FLAG_MASK;
|
||
ip_flag_frags_more = DEF_BIT_IS_SET(ip_flags, NET_IP_HDR_FLAG_FRAG_MORE);
|
||
if (ip_flag_frags_more != DEF_NO) { /* If 'More Frags' flag set ... */
|
||
ip_frag_offset = pbuf_hdr->IP_Flags_FragOffset & NET_IP_HDR_FRAG_OFFSET_MASK;
|
||
if (ip_frag_offset != NET_IP_HDR_FRAG_OFFSET_NONE) { /* ... & frag offset != 0, ... */
|
||
*perr = NET_ICMP_ERR_TX_INVALID_FRAG; /* ... rtn err for non-initial frag (see Note #1a4). */
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ----------------- CHK ICMP ERR MSG ----------------- */
|
||
if (pip_hdr->Protocol == NET_IP_HDR_PROTOCOL_ICMP) { /* If rx'd IP datagram is ICMP, ... */
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (pbuf_hdr->ICMP_MsgIx == NET_BUF_IX_NONE) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrRxInvalidBufIxCtr);
|
||
*perr = NET_BUF_ERR_INVALID_IX;
|
||
return;
|
||
}
|
||
#endif
|
||
picmp_hdr = (NET_ICMP_HDR *)&pbuf->Data[pbuf_hdr->ICMP_MsgIx];
|
||
|
||
switch (picmp_hdr->Type) { /* ... chk ICMP msg type & ... */
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ERR_MSG; /* ... rtn err for ICMP err msgs (see Note #1a1). */
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
case NET_ICMP_MSG_TYPE_ECHO_REPLY:
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
case NET_ICMP_MSG_TYPE_TS_REPLY:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REPLY:
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
ptr_max_protocol = pbuf_hdr->ICMP_MsgLen; /* See Note #6c. */
|
||
#endif
|
||
break;
|
||
|
||
#if 0 /* ---------------- UNSUPPORTED TYPES ----------------- */
|
||
/* See Note #5. */
|
||
case NET_ICMP_MSG_TYPE_REDIRECT:
|
||
case NET_ICMP_MSG_TYPE_ROUTE_REQ:
|
||
case NET_ICMP_MSG_TYPE_ROUTE_AD:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REQ:
|
||
/* 'break' intentionally omitted; do NOT move from the */
|
||
/* ... following case : 'default'. */
|
||
#endif
|
||
|
||
default:
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
} else { /* #### See Note #6d. */
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
ptr_max_protocol = 0;
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------- VALIDATE ICMP ERR MSG TYPE/CODE/PTR -------- */
|
||
switch (type) {
|
||
case NET_ICMP_MSG_TYPE_DEST_UNREACH:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_DEST_PROTOCOL:
|
||
case NET_ICMP_MSG_CODE_DEST_PORT:
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_CODE_DEST_NET:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST:
|
||
case NET_ICMP_MSG_CODE_DEST_FRAG_NEEDED:
|
||
case NET_ICMP_MSG_CODE_DEST_ROUTE_FAIL:
|
||
case NET_ICMP_MSG_CODE_DEST_NET_UNKNOWN:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST_UNKNOWN:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST_ISOLATED:
|
||
case NET_ICMP_MSG_CODE_DEST_NET_TOS:
|
||
case NET_ICMP_MSG_CODE_DEST_HOST_TOS:
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_SRC_QUENCH:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_SRC_QUENCH:
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TIME_EXCEED:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_TIME_EXCEED_TTL:
|
||
case NET_ICMP_MSG_CODE_TIME_EXCEED_FRAG_REASM:
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_PARAM_PROB:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR:
|
||
case NET_ICMP_MSG_CODE_PARAM_PROB_OPT_MISSING:
|
||
/* Validate ICMP Param Prob Msg ptr (see Note #6). */
|
||
#if 0 /* See Note #6b. */
|
||
if (ptr < NET_ICMP_PTR_IX_BASE) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrPtrCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_PTR;
|
||
}
|
||
#endif
|
||
ptr_max = pbuf_hdr->IP_HdrLen + ptr_max_protocol;
|
||
if (ptr >= ptr_max) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrPtrCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_PTR;
|
||
}
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
case NET_ICMP_MSG_TYPE_ECHO_REPLY:
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
case NET_ICMP_MSG_TYPE_TS_REPLY:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REPLY:
|
||
*perr = NET_ICMP_ERR_TX_INVALID_ERR_MSG;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
|
||
/*$PAGE*/
|
||
#if 0 /* ---------------- UNSUPPORTED TYPES ----------------- */
|
||
/* See Note #5. */
|
||
case NET_ICMP_MSG_TYPE_REDIRECT:
|
||
case NET_ICMP_MSG_TYPE_ROUTE_REQ:
|
||
case NET_ICMP_MSG_TYPE_ROUTE_AD:
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REQ:
|
||
/* 'break' intentionally omitted; do NOT move from the */
|
||
/* ... following case : 'default'. */
|
||
#endif
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
#else /* Prevent compiler warnings. */
|
||
(void)&type;
|
||
(void)&code;
|
||
(void)&ptr;
|
||
#endif
|
||
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxMsgReqValidate()
|
||
*
|
||
* Description : Validate parameters for ICMP Request Message transmit.
|
||
*
|
||
* Argument(s) : type ICMP Request Message type (see Note #1) :
|
||
*
|
||
* NET_ICMP_MSG_TYPE_ECHO_REQ
|
||
* NET_ICMP_MSG_TYPE_TS_REQ
|
||
* NET_ICMP_MSG_TYPE_ADDR_MASK_REQ
|
||
*
|
||
* code ICMP Request Message code (see Note #1).
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE Transmit parameters successfully validated
|
||
* for ICMP transmit request message.
|
||
* NET_ICMP_ERR_INVALID_TYPE Invalid/unknown ICMP message type.
|
||
* NET_ICMP_ERR_INVALID_CODE Invalid/unknown ICMP message code.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_TxMsgReq().
|
||
*
|
||
* Note(s) : (1) See 'net_icmp.h ICMP MESSAGE TYPES & CODES Notes #2 & #3' for supported ICMP message
|
||
* types & codes.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
static void NetICMP_TxMsgReqValidate (CPU_INT08U type,
|
||
CPU_INT08U code,
|
||
NET_ERR *perr)
|
||
{
|
||
#if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
|
||
/* --------- VALIDATE ICMP REQ MSG TYPE/CODE ---------- */
|
||
switch (type) {
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_ECHO_REQ:
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_TS_REQ:
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_ADDR_MASK_REQ:
|
||
switch (code) {
|
||
case NET_ICMP_MSG_CODE_ADDR_MASK_REQ:
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrCodeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_CODE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
break;
|
||
|
||
|
||
default:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxHdrTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxMsgReply()
|
||
*
|
||
* Description : (1) Transmit ICMP Reply Message in response to received ICMP Request Message :
|
||
*
|
||
* (a) Process ICMP Reply Message :
|
||
*
|
||
* (1) The following ICMP Reply Messages require receive processing :
|
||
*
|
||
* (A) Timestamp Reply Message
|
||
*
|
||
* (1) "The Receive Timestamp is the time the echoer first touched it on receipt"
|
||
* (RFC #792, Section 'Timestamp or Timestamp Reply Message : Description').
|
||
*
|
||
* (b) Get buffer for ICMP Reply Message :
|
||
*
|
||
* (1) Copy ICMP Request Message into ICMP Reply Message
|
||
* (2) Initialize ICMP Reply Message buffer controls
|
||
*
|
||
* (c) Prepare ICMP Reply Message's IP header :
|
||
*
|
||
* (1) RFC #1349, Section 5.1 specifies that "an ICMP reply message is sent with the same
|
||
* value in the TOS field as was used in the corresponding ICMP request message".
|
||
*
|
||
* (2) RFC #1122, Sections 3.2.2.6 & 3.2.2.8 specify that "if a Record Route and/or Time
|
||
* Stamp option is received in [an ICMP Request, these options] SHOULD be updated ...
|
||
* and included in the IP header of the ... Reply message". Also "if a Source Route
|
||
* option is received ... the return route MUST be reversed and used as a Source Route
|
||
* option for the ... Reply message".
|
||
*
|
||
* #### These IP header option requirements for ICMP Reply Messages are NOT yet implemented.
|
||
*
|
||
* (d) Prepare ICMP Reply Message :
|
||
*
|
||
* (1) Echo Reply Message
|
||
*
|
||
* (A) "To form an echo reply message, the source and destination addresses are simply
|
||
* reversed, the type code changed to [reply], and the checksum recomputed"
|
||
* (RFC #792, Section 'Echo or Echo Reply Message : Addresses').
|
||
*
|
||
* (2) Timestamp Reply Message
|
||
*
|
||
* (A) "The Transmit Timestamp is the time the echoer last touched the message on sending
|
||
* it" (RFC #792, Section 'Timestamp or Timestamp Reply Message : Description').
|
||
*
|
||
* (B) "To form a timestamp reply message, the source and destination addresses are
|
||
* simply reversed, the type code changed to [reply], and the checksum recomputed"
|
||
* (RFC #792, Section 'Timestamp or Timestamp Reply Message : Addresses').
|
||
*
|
||
* (3) Some ICMP Reply Message fields are copied directly from the ICMP Request Message.
|
||
*
|
||
* (A) ICMP Reply Message Identification & Sequence Number fields were NOT validated
|
||
* or converted from network-order to host-order (see 'NetICMP_RxPktValidate()
|
||
* Notes #1b2C & #1b2D') & therefore do NOT need to be converted from host-order
|
||
* to network-order.
|
||
*
|
||
* (e) Transmit ICMP Reply Message
|
||
*
|
||
* (f) Free ICMP Reply Message buffer
|
||
*
|
||
* (g) Update transmit statistics
|
||
*
|
||
*$PAGE*
|
||
* Argument(s) : pbuf Pointer to network buffer that received ICMP packet.
|
||
* ---- Argument checked in NetICMP_Rx().
|
||
*
|
||
* pbuf_hdr Pointer to network buffer header.
|
||
* -------- Argument validated in NetICMP_Rx().
|
||
*
|
||
* picmp_hdr Pointer to received packet's ICMP header.
|
||
* --------- Argument validated in NetICMP_Rx()/NetICMP_RxPktValidateBuf().
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE ICMP Reply Message successfully transmitted.
|
||
*
|
||
* --- RETURNED BY NetICMP_TxPktDiscard() : ---
|
||
* NET_ERR_TX Transmit error; packet discarded.
|
||
*
|
||
* --------- RETURNED BY NetIP_Tx() : ---------
|
||
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_Rx().
|
||
*
|
||
* Note(s) : (2) Default case already invalidated in NetICMP_RxPktValidate(). However, the default case
|
||
* is included as an extra precaution in case 'Type' is incorrectly modified.
|
||
*
|
||
* (3) (a) "Data received in an ICMP Echo Request MUST be entirely included in the resulting
|
||
* Echo Reply. However, if sending the Echo Reply requires intentional fragmentation
|
||
* that is not implemented, the datagram MUST be truncated to maximum transmission
|
||
* size ... and sent" (RFC #1122, Section 3.2.2.6).
|
||
*
|
||
* See also 'net_ip.h Note #1e'.
|
||
*
|
||
* (b) In case the maximum network buffer size is smaller than the ICMP message data length,
|
||
* the ICMP Echo Request Message data should be similarly truncated in order to transmit
|
||
* the ICMP Echo Reply Message.
|
||
*
|
||
* (4) Some buffer controls were previously initialized in NetBuf_Get() when the buffer
|
||
* was allocated earlier in this function. These buffer controls do NOT need to be
|
||
* re-initialized but are shown for completeness.
|
||
*
|
||
* (5) (a) ICMP message Check-Sum MUST be calculated AFTER the entire ICMP message has been
|
||
* prepared. In addition, ALL multi-octet words are converted from host-order to
|
||
* network-order since "the sum of 16-bit integers can be computed in either byte
|
||
* order" [RFC #1071, Section 2.(B)].
|
||
*
|
||
* (b) ICMP message Check-Sum field MUST be cleared to '0' BEFORE the ICMP message
|
||
* Check-Sum is calculated (see RFC #792, Sections 'Echo or Echo Reply Message :
|
||
* Checksum' & 'Timestamp or Timestamp Reply Message : Checksum').
|
||
*
|
||
* (c) The ICMP message Check-Sum field is returned in network-order & MUST NOT be re-
|
||
* converted back to host-order (see 'net_util.c NetUtil_16BitOnesCplChkSumHdrCalc()
|
||
* Note #3b' & 'net_util.c NetUtil_16BitOnesCplChkSumDataCalc() Note #4b').
|
||
*
|
||
* (6) Network buffer already freed by lower layer; only increment error counter.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
static void NetICMP_TxMsgReply (NET_BUF *pbuf,
|
||
NET_BUF_HDR *pbuf_hdr,
|
||
NET_ICMP_HDR *picmp_hdr,
|
||
NET_ERR *perr)
|
||
{
|
||
#if (((NET_CTR_CFG_STAT_EN == DEF_ENABLED) || \
|
||
(NET_CTR_CFG_ERR_EN == DEF_ENABLED)) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
#if 0 /* DISABLED while NOT yet implemented. */
|
||
NET_IP_OPT_CFG_ROUTE_TS msg_opt_route_ts;
|
||
#endif
|
||
NET_ICMP_HDR_ECHO *picmp_hdr_echo;
|
||
NET_ICMP_HDR_TS *picmp_hdr_ts;
|
||
NET_BUF *pmsg_req;
|
||
NET_BUF *pmsg_reply;
|
||
NET_BUF_HDR *pmsg_req_hdr;
|
||
NET_BUF_HDR *pmsg_reply_hdr;
|
||
NET_IP_OPT_CFG_ROUTE_TS *pmsg_opt_cfg_route_ts;
|
||
NET_IP_HDR *pip_hdr;
|
||
NET_BUF_SIZE buf_size_max;
|
||
CPU_INT16U msg_size_hdr;
|
||
CPU_INT16U msg_len;
|
||
CPU_INT16U msg_len_min;
|
||
CPU_INT16U msg_len_rem;
|
||
CPU_INT16U msg_ix;
|
||
CPU_INT16U msg_reply_ix;
|
||
CPU_INT16U msg_reply_len;
|
||
CPU_INT16U msg_chk_sum;
|
||
CPU_INT16U flags;
|
||
CPU_INT08U *pmsg_req_data;
|
||
NET_TS ts;
|
||
NET_IP_TOS TOS;
|
||
NET_ERR err;
|
||
|
||
|
||
|
||
/* ------------- PROCESS ICMP REPLY MSGs -------------- */
|
||
switch (picmp_hdr->Type) {
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ:
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_ECHO;
|
||
msg_len_min = NET_ICMP_MSG_LEN_MIN_ECHO;
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TS_REQ:
|
||
picmp_hdr_ts = (NET_ICMP_HDR_TS *)picmp_hdr;
|
||
ts = NetUtil_TS_Get(); /* See Note #1a1A1. */
|
||
NET_UTIL_VAL_COPY_SET_NET_32(&picmp_hdr_ts->TS_Rx, &ts);
|
||
msg_size_hdr = NET_ICMP_HDR_SIZE_TS;
|
||
msg_len_min = NET_ICMP_MSG_LEN_MIN_TS;
|
||
break;
|
||
|
||
|
||
default: /* See Note #2. */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* -------------- GET ICMP REPLY MSG BUF -------------- */
|
||
msg_len = pbuf_hdr->ICMP_MsgLen; /* Adjust req msg len for reply msg len. */
|
||
|
||
if (msg_len > NET_IP_MTU) { /* If msg len > MTU, ... */
|
||
if (picmp_hdr->Type != NET_ICMP_MSG_TYPE_ECHO_REQ) { /* ... for Echo Req Msg ONLY, ... */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
return;
|
||
}
|
||
msg_len = NET_IP_MTU; /* ... truncate msg len (see Note #3a). */
|
||
}
|
||
|
||
msg_ix = NET_BUF_DATA_TX_IX;
|
||
buf_size_max = NetBuf_GetMaxSize((NET_BUF *)0,
|
||
(NET_BUF_SIZE)msg_ix);
|
||
if ((NET_BUF_SIZE)msg_len > buf_size_max) { /* If msg len > max buf size, ... */
|
||
msg_len = (CPU_INT16U)buf_size_max; /* ... truncate msg len (see Note #3b). */
|
||
}
|
||
|
||
if (msg_len < msg_len_min) { /* If msg len < min msg len, rtn err. */
|
||
NetICMP_TxPktDiscard((NET_BUF *)0, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxInvalidLenCtr);
|
||
return;
|
||
}
|
||
|
||
|
||
pmsg_reply = NetBuf_Get((NET_BUF_SIZE) msg_len, /* Get reply msg buf. */
|
||
(NET_BUF_SIZE) msg_ix,
|
||
(CPU_INT16U ) NET_BUF_FLAG_NONE,
|
||
(NET_ERR *)&err);
|
||
if (err != NET_BUF_ERR_NONE) {
|
||
NetICMP_TxPktDiscard(pmsg_reply, perr);
|
||
return;
|
||
}
|
||
|
||
|
||
pmsg_req = pbuf;
|
||
msg_reply_ix = msg_ix;
|
||
msg_len_rem = msg_len;
|
||
|
||
while ((pmsg_req != (NET_BUF *)0) && (msg_len_rem > 0)) { /* For ALL ICMP req msg pkt bufs, ... */
|
||
/* ... copy rx'd ICMP req msg into ICMP reply tx buf. */
|
||
pmsg_req_hdr = &pmsg_req->Hdr;
|
||
pmsg_req_data = &pmsg_req->Data[pmsg_req_hdr->ICMP_MsgIx];
|
||
msg_reply_len = pmsg_req_hdr->IP_DataLen; /* Each pkt buf's IP data is ICMP req msg data. */
|
||
if (msg_reply_len > msg_len_rem) { /* If req msg pkt buf data len > rem msg len, ... */
|
||
msg_reply_len = msg_len_rem; /* ... truncate req msg pkt buf data len. */
|
||
}
|
||
|
||
NetBuf_DataWr((NET_BUF *) pmsg_reply,
|
||
(NET_BUF_SIZE) msg_reply_ix,
|
||
(NET_BUF_SIZE) msg_reply_len,
|
||
(CPU_INT08U *) pmsg_req_data,
|
||
(NET_ERR *)&err);
|
||
if (err != NET_BUF_ERR_NONE) {
|
||
NetICMP_TxPktDiscard(pmsg_reply, perr);
|
||
return;
|
||
}
|
||
|
||
msg_reply_ix += msg_reply_len;
|
||
msg_len_rem -= msg_reply_len;
|
||
|
||
pmsg_req = (NET_BUF *)pmsg_req_hdr->NextBufPtr;
|
||
}
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (msg_len_rem > 0) { /* If entire ICMP req msg NOT copied, rtn err. */
|
||
NetICMP_TxPktDiscard(pmsg_reply, perr);
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxInvalidLenCtr);
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
/* Init reply msg buf ctrls. */
|
||
pmsg_reply_hdr = &pmsg_reply->Hdr;
|
||
pmsg_reply_hdr->ICMP_MsgIx = (CPU_INT16U )msg_ix;
|
||
pmsg_reply_hdr->ICMP_MsgLen = (CPU_INT16U )msg_len;
|
||
pmsg_reply_hdr->ICMP_HdrLen = (CPU_INT16U )msg_size_hdr;
|
||
pmsg_reply_hdr->TotLen = (NET_BUF_SIZE)pmsg_reply_hdr->ICMP_MsgLen;
|
||
pmsg_reply_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_ICMP;
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ------------ PREPARE ICMP REPLY IP HDR ------------- */
|
||
pip_hdr = (NET_IP_HDR *)&pbuf->Data[pbuf_hdr->IP_HdrIx];
|
||
TOS = pip_hdr->TOS; /* See Note #1c1. */
|
||
flags = NET_IP_FLAG_NONE; /* See Note #1c2. */
|
||
pmsg_opt_cfg_route_ts = (NET_IP_OPT_CFG_ROUTE_TS *)0;
|
||
|
||
|
||
|
||
/* -------------- PREPARE ICMP REPLY MSG -------------- */
|
||
switch (picmp_hdr->Type) {
|
||
case NET_ICMP_MSG_TYPE_ECHO_REQ: /* See Note #1d1. */
|
||
picmp_hdr_echo = (NET_ICMP_HDR_ECHO *)&pmsg_reply->Data[pmsg_reply_hdr->ICMP_MsgIx];
|
||
picmp_hdr_echo->Type = NET_ICMP_MSG_TYPE_ECHO_REPLY;
|
||
#if 0 /* Copied from ICMP req msg (see Note #1d3). */
|
||
picmp_hdr_echo->Code = NET_ICMP_MSG_CODE_ECHO;
|
||
/* See Note #1d3A. */
|
||
(void)&picmp_hdr_echo->ID;
|
||
(void)&picmp_hdr_echo->SeqNbr;
|
||
#endif
|
||
/* Calc ICMP msg data len. */
|
||
if (pbuf_hdr->ICMP_MsgLen > msg_len_min) {
|
||
pmsg_reply_hdr->DataIx = (CPU_INT16U )(pmsg_reply_hdr->ICMP_MsgIx + msg_len_min);
|
||
pmsg_reply_hdr->DataLen = (NET_BUF_SIZE)(pmsg_reply_hdr->ICMP_MsgLen - msg_len_min);
|
||
#if 0 /* Init'd in NetBuf_Get() [see Note #4]. */
|
||
} else {
|
||
pmsg_reply_hdr->DataIx = NET_BUF_IX_NONE;
|
||
pmsg_reply_hdr->DataLen = 0;
|
||
#endif
|
||
}
|
||
/* Calc ICMP msg chk sum (see Note #5). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_echo->ChkSum, 0x0000); /* Clr chk sum (see Note #5b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumDataCalc((void *) pmsg_reply,
|
||
(void *) 0,
|
||
(CPU_INT16U) 0,
|
||
(NET_ERR *)&err);
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_echo->ChkSum, &msg_chk_sum); /* Copy chk sum in net order (see Note #5c).*/
|
||
break;
|
||
|
||
|
||
case NET_ICMP_MSG_TYPE_TS_REQ: /* See Note #1d2. */
|
||
picmp_hdr_ts = (NET_ICMP_HDR_TS *)&pmsg_reply->Data[pmsg_reply_hdr->ICMP_MsgIx];
|
||
ts = NetUtil_TS_Get(); /* See Note #1d2A. */
|
||
NET_UTIL_VAL_COPY_SET_NET_32(&picmp_hdr_ts->TS_Tx, &ts);
|
||
|
||
picmp_hdr_ts->Type = NET_ICMP_MSG_TYPE_TS_REPLY;
|
||
#if 0 /* Copied from ICMP req msg (see Note #1d3). */
|
||
picmp_hdr_ts->Code = NET_ICMP_MSG_CODE_TS;
|
||
/* See Note #1d3A. */
|
||
(void)&picmp_hdr_ts->ID;
|
||
(void)&picmp_hdr_ts->SeqNbr;
|
||
#endif
|
||
/* NULL ICMP msg data len. */
|
||
#if 0 /* Init'd in NetBuf_Get() [see Note #4]. */
|
||
pmsg_reply_hdr->DataIx = NET_BUF_IX_NONE;
|
||
pmsg_reply_hdr->DataLen = 0;
|
||
#endif
|
||
/* Calc ICMP msg chk sum (see Note #5). */
|
||
NET_UTIL_VAL_SET_NET_16(&picmp_hdr_ts->ChkSum, 0x0000); /* Clr chk sum (see Note #5b). */
|
||
msg_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *) picmp_hdr_ts,
|
||
(CPU_INT16U) pmsg_reply_hdr->ICMP_MsgLen,
|
||
(NET_ERR *)&err);
|
||
NET_UTIL_VAL_COPY_16(&picmp_hdr_ts->ChkSum, &msg_chk_sum); /* Copy chk sum in net order (see Note #5c).*/
|
||
break;
|
||
|
||
|
||
default: /* See Note #2. */
|
||
NetICMP_TxPktDiscard(pmsg_reply, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
if (err != NET_UTIL_ERR_NONE) { /* Chk err from NetUtil_16BitOnesCplChkSum()'s. */
|
||
NetICMP_TxPktDiscard(pmsg_reply, perr);
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ---------------- TX ICMP REPLY MSG ----------------- */
|
||
NetIP_Tx((NET_BUF *)pmsg_reply,
|
||
(NET_IP_ADDR)pbuf_hdr->IP_AddrDest,
|
||
(NET_IP_ADDR)pbuf_hdr->IP_AddrSrc,
|
||
(NET_IP_TOS )TOS,
|
||
(NET_IP_TTL )NET_IP_TTL_DFLT,
|
||
(CPU_INT16U )flags,
|
||
(void *)pmsg_opt_cfg_route_ts,
|
||
(NET_ERR *)perr);
|
||
|
||
|
||
|
||
/* ------ FREE ICMP REPLY MSG / UPDATE TX STATS ------- */
|
||
switch (*perr) {
|
||
case NET_IP_ERR_NONE:
|
||
NetICMP_TxPktFree(pmsg_reply);
|
||
NET_CTR_STAT_INC(NetICMP_StatTxMsgCtr);
|
||
NET_CTR_STAT_INC(NetICMP_StatTxMsgReplyCtr);
|
||
break;
|
||
|
||
|
||
case NET_ERR_TX:
|
||
NET_CTR_ERR_INC(NetICMP_ErrTxPktDiscardedCtr); /* See Note #6. */
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
|
||
|
||
case NET_ERR_INIT_INCOMPLETE:
|
||
default:
|
||
NetICMP_TxPktDiscard(pmsg_reply, perr);
|
||
return; /* Prevent 'break NOT reachable' compiler warning. */
|
||
}
|
||
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxPktFree()
|
||
*
|
||
* Description : Free network buffer.
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_TxMsgErr(),
|
||
* NetICMP_TxMsgReq(),
|
||
* NetICMP_TxMsgReply().
|
||
*
|
||
* Note(s) : (1) (a) Although ICMP Transmit initially requests the network buffer for transmit,
|
||
* the ICMP layer does NOT maintain a reference to the buffer.
|
||
*
|
||
* (b) Also, since the network interface layer frees ALL unreferenced buffers
|
||
* after successful transmission [see 'net_if_pkt.c NetIF_Pkt_TxPktFree()'
|
||
* or 'net_if_char.c NetIF_Char_TxPktFree()'], the ICMP layer MUST not
|
||
* free the transmit buffer.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void NetICMP_TxPktFree (NET_BUF *pbuf)
|
||
{
|
||
(void)&pbuf; /* Prevent compiler warning (see Note #1). */
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_TxPktDiscard()
|
||
*
|
||
* Description : On any Transmit packet errors, discard packet & buffer.
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer.
|
||
*
|
||
* perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ERR_TX Transmit error; packet discarded.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_TxMsgErr(),
|
||
* NetICMP_TxMsgReq(),
|
||
* NetICMP_TxMsgReply().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void NetICMP_TxPktDiscard (NET_BUF *pbuf,
|
||
NET_ERR *perr)
|
||
{
|
||
NET_CTR *pctr;
|
||
|
||
|
||
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
|
||
pctr = (NET_CTR *)&NetICMP_ErrTxPktDiscardedCtr;
|
||
#else
|
||
pctr = (NET_CTR *) 0;
|
||
#endif
|
||
NetBuf_FreeBuf((NET_BUF *)pbuf,
|
||
(NET_CTR *)pctr);
|
||
|
||
*perr = NET_ERR_TX;
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuench()
|
||
*
|
||
* Description : When network low-resources status is set, transmit periodic ICMP Source Quench Error
|
||
* Messages to all individual IP source host addresses sending IP packets to this host
|
||
* (see 'NetICMP_HandlerRx() Note #1a').
|
||
*
|
||
* (1) Validate IP Source Host Address :
|
||
*
|
||
* (a) ICMP Source Quench Error Messages should be transmitted to individual host addresses
|
||
* ONLY.
|
||
*
|
||
* (b) Therefore, ICMP Source Quench Error Messages SHOULD NOT be transmitted to the following
|
||
* IP source host addresses :
|
||
*
|
||
* (1) This Host RFC #1122, Section 3.2.1.3.(a)
|
||
* (2) Specified Host RFC #1122, Section 3.2.1.3.(b)
|
||
*
|
||
* (c) See also 'net_ip.c NetIP_RxPktValidate() Note #9c' for invalid IP source host addresses.
|
||
*
|
||
* (2) Search ICMP Transmit Source Quench List for entry with corresponding IP source host address
|
||
* (see Notes #4a & #4c).
|
||
*
|
||
* (3) Transmit ICMP Source Quench Error Message to all individual IP source host addresses sending
|
||
* IP packets to this host.
|
||
*
|
||
*
|
||
* Argument(s) : pbuf Pointer to network buffer that received an IP packet.
|
||
* ---- Argument validated in NetICMP_HandlerRx()
|
||
* by NetIP_Rx().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerRx().
|
||
*$PAGE*
|
||
* Note(s) : (4) (a) ICMP Transmit Source Quench List totals the number of ICMP Source Quench Error Messages
|
||
* transmitted to specific IP source host addresses.
|
||
*
|
||
* (b) ICMP transmit source quench entries are linked to form an ICMP Transmit Source Quench
|
||
* List. In the diagram below, the horizontal row represents the list of ICMP transmit
|
||
* source quench entries.
|
||
*
|
||
* (1) 'NetICMP_TxSrcQuenchListHead' points to the head of the list;
|
||
* 'NetICMP_TxSrcQuenchListTail' points to the tail of the list.
|
||
*
|
||
* (2) ICMP transmit source quench entries' 'PrevPtr' & 'NextPtr' doubly-link each
|
||
* entry to form the ICMP Transmit Source Quench List.
|
||
*
|
||
* (c) For any ICMP Transmit Source Quench List lookup, all ICMP transmit source quench
|
||
* entries are searched in order to find the entry with the appropriate IP address--
|
||
* i.e. the entry with the corresponding source host address (see Note #4a).
|
||
*
|
||
* (d) New ICMP transmit source quench entries are added at the head of the ICMP Transmit
|
||
* Source Quench List. This allows faster lookup for recently added entries.
|
||
*
|
||
* (e) As ICMP transmit source quench entries are added into the list, older entries migrate
|
||
* to the tail of the list. If the list is full & a new entry is needed, then the oldest
|
||
* entry at the tail of the list is removed for allocation.
|
||
*
|
||
* (f) The ICMP Transmit Source Quench List is cleared only when the network low-resources
|
||
* status clears (see 'NetICMP_HandlerRx() Note #1b').
|
||
*
|
||
*
|
||
* | |
|
||
* |<------- List of ICMP Transmit Source Quench Entries ------->|
|
||
* | (see Note #4b) |
|
||
*
|
||
* New ICMP entries Oldest entry in ICMP
|
||
* inserted at head Transmit Source Quench List
|
||
* (see Note #4d) (see Note #4e)
|
||
*
|
||
* | NextPtr |
|
||
* | (see Note #4b2) |
|
||
* v | v
|
||
* |
|
||
* Head of ICMP ------- ------- v ------- ------- ------- (see Note #4b1)
|
||
* Transmit Source ---->| |------>| |------>| |------>| |------>| |
|
||
* Quench List | | | | | | | | | | Tail of ICMP
|
||
* | |<------| |<------| |<------| |<------| |<---- Transmit Source
|
||
* (see Note #4b1) ------- ------- ^ ------- ------- ------- Quench List
|
||
* |
|
||
* |
|
||
* PrevPtr
|
||
* (see Note #4b2)
|
||
*
|
||
*
|
||
* (5) The following IP header fields MUST be decoded &/or converted from network-order to host-
|
||
* order BEFORE any ICMP Source Quench List search & error message transmit (see 'net_ip.c
|
||
* NetIP_RxPktValidate() Note #3') :
|
||
*
|
||
* (a) Source Address
|
||
*
|
||
* (6) (a) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
|
||
*
|
||
* (b) Default case already invalidated in NetIP_RxPktValidate(). However, the default case
|
||
* is included as an extra precaution in case 'IP_AddrSrc' is incorrectly modified.
|
||
*
|
||
* (7) During ICMP transmit source quench entry initialization, some entry values were previously
|
||
* initialized in NetICMP_HandlerTxSrcQuenchGet() when the entry was allocated from the pool.
|
||
* These entry values do NOT need to be re-initialized but are shown for completeness.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuench (NET_BUF *pbuf)
|
||
{
|
||
NET_BUF_HDR *pbuf_hdr;
|
||
NET_ICMP_TX_SRC_QUENCH *ptx_src_quench;
|
||
NET_ICMP_TX_SRC_QUENCH *pentry_next;
|
||
CPU_BOOLEAN found;
|
||
CPU_BOOLEAN tx_src_quench;
|
||
NET_ERR err;
|
||
|
||
|
||
pbuf_hdr = &pbuf->Hdr;
|
||
|
||
/* ----------- VALIDATE IP SRC ADDR ----------- */
|
||
/* See Notes #1 & #5a. */
|
||
if (pbuf_hdr->IP_AddrSrc == NET_IP_ADDR_THIS_HOST) { /* Chk 'This Host' (see Note #1b1). */
|
||
return;
|
||
}
|
||
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
|
||
/* Chk Class-A specified host (see Note #1b2). */
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
|
||
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
|
||
return;
|
||
}
|
||
|
||
} else if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
|
||
/* Chk Class-B specified host (see Note #1b2). */
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
|
||
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
|
||
return;
|
||
}
|
||
|
||
} else if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
|
||
/* Chk Class-C specified host (see Note #1b2). */
|
||
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
|
||
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
|
||
return;
|
||
}
|
||
|
||
} else { /* Discard invalid addr class (see Note #6). */
|
||
return;
|
||
}
|
||
|
||
|
||
/* ------- SRCH ICMP TX SRC QUENCH LIST ------- */
|
||
ptx_src_quench = NetICMP_TxSrcQuenchListHead; /* Start @ ICMP Tx Src Quench List head. */
|
||
found = DEF_NO;
|
||
tx_src_quench = DEF_NO;
|
||
|
||
while ((ptx_src_quench != (NET_ICMP_TX_SRC_QUENCH *)0) && /* Srch ICMP Tx Src Quench List ... */
|
||
(found == DEF_NO)) { /* ... until entry found. */
|
||
|
||
pentry_next = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench->NextPtr;
|
||
|
||
found = ((NET_IP_ADDR)pbuf_hdr->IP_AddrSrc ==
|
||
(NET_IP_ADDR)ptx_src_quench->Addr) ? DEF_YES : DEF_NO;
|
||
|
||
if (found != DEF_YES) { /* If NOT found, adv to next entry. */
|
||
ptx_src_quench = pentry_next;
|
||
} else {
|
||
ptx_src_quench->TxCtr++;
|
||
if (ptx_src_quench->TxCtr >= NetICMP_TxSrcQuenchTxTh_nbr) { /* If tx ctr > th, */
|
||
tx_src_quench = DEF_YES; /* .. tx ICMP Src Quench Err Msg. */
|
||
}
|
||
}
|
||
}
|
||
|
||
if (found != DEF_YES) { /* If ICMP tx src quench entry NOT found, ... */
|
||
ptx_src_quench = NetICMP_HandlerTxSrcQuenchGet(&err); /* ... get new entry, ... */
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
if (ptx_src_quench == (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
return;
|
||
}
|
||
#endif
|
||
/* ... init new entry, ... */
|
||
ptx_src_quench->Addr = (NET_IP_ADDR)pbuf_hdr->IP_AddrSrc;
|
||
#if 0 /* Init'd in NetICMP_HandlerTxSrcQuenchGet() .. */
|
||
/* ... (see Note #7). */
|
||
ptx_src_quench->TxCtr = 0;
|
||
/* Init'd in NetICMP_HandlerTxSrcQuenchInsert(). */
|
||
ptx_src_quench->PrevPtr = (void *)0;
|
||
ptx_src_quench->NextPtr = (void *)0;
|
||
#endif
|
||
|
||
NetICMP_HandlerTxSrcQuenchInsert(ptx_src_quench); /* ... insert new entry into list, & ... */
|
||
|
||
tx_src_quench = DEF_YES; /* ... tx ICMP Src Quench Err Msg. */
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/* ------------ TX ICMP SRC QUENCH ERR MSG ------------ */
|
||
if (tx_src_quench != DEF_NO) {
|
||
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_SRC_QUENCH, NET_ICMP_MSG_CODE_SRC_QUENCH, NET_ICMP_MSG_PTR_NONE, &err);
|
||
|
||
if (err == NET_ICMP_ERR_NONE) { /* If ICMP Src Quench Err Msg successfully tx'd, ... */
|
||
ptx_src_quench->TxCtr = 0; /* ... clr tx ctr. */
|
||
|
||
} else if (found != DEF_YES) { /* Else if new entry, set tx ctr to th val for retry. */
|
||
ptx_src_quench->TxCtr = NetICMP_TxSrcQuenchTxTh_nbr;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchClrList()
|
||
*
|
||
* Description : Clear ICMP Transmit Source Quench List when network low-resources status clears.
|
||
*
|
||
* Argument(s) : none.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerRx().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchClrList (void)
|
||
{
|
||
NET_ICMP_TX_SRC_QUENCH *ptx_src_quench;
|
||
NET_ICMP_TX_SRC_QUENCH *pentry_next;
|
||
|
||
|
||
ptx_src_quench = NetICMP_TxSrcQuenchListHead;
|
||
while (ptx_src_quench != (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
pentry_next = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench->NextPtr;
|
||
NetICMP_HandlerTxSrcQuenchFree(ptx_src_quench);
|
||
ptx_src_quench = pentry_next;
|
||
}
|
||
|
||
NetICMP_TxSrcQuenchListHead = (NET_ICMP_TX_SRC_QUENCH *)0;
|
||
NetICMP_TxSrcQuenchListTail = (NET_ICMP_TX_SRC_QUENCH *)0;
|
||
}
|
||
#endif
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchClr()
|
||
*
|
||
* Description : Clear ICMP transmit source quench entry controls.
|
||
*
|
||
* Argument(s) : ptx_src_quench Pointer to an ICMP transmit source quench entry.
|
||
* -------------- Argument validated in NetICMP_Init(),
|
||
* NetICMP_HandlerTxSrcQuenchGet(),
|
||
* NetICMP_HandlerTxSrcQuenchFree().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_Init(),
|
||
* NetICMP_HandlerTxSrcQuenchGet(),
|
||
* NetICMP_HandlerTxSrcQuenchFree().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchClr (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench)
|
||
{
|
||
ptx_src_quench->PrevPtr = (void *)0;
|
||
ptx_src_quench->NextPtr = (void *)0;
|
||
ptx_src_quench->Addr = (NET_IP_ADDR)NET_IP_ADDR_NONE;
|
||
ptx_src_quench->TxCtr = 0;
|
||
ptx_src_quench->Flags = NET_ICMP_FLAG_NONE;
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchGet()
|
||
*
|
||
* Description : (1) Allocate & initialize an ICMP transmit source quench entry :
|
||
*
|
||
* (a) Get an ICMP transmit source quench entry
|
||
* (b) Validate ICMP transmit source quench entry
|
||
* (c) Initialize ICMP transmit source quench entry
|
||
* (d) Update ICMP transmit source quench pool statistics
|
||
* (e) Return pointer to ICMP transmit source quench entry
|
||
* OR
|
||
* Null pointer & error code, on failure
|
||
*
|
||
* (2) The ICMP transmit source quench pool is implemented as a stack :
|
||
*
|
||
* (a) 'NetICMP_TxSrcQuenchPoolPtr' points to the head of the pool.
|
||
*
|
||
* (b) Entries' 'NextPtr's link each entry to form the pool stack.
|
||
*
|
||
* (c) Entries are inserted & removed at the head of the pool stack.
|
||
*
|
||
*
|
||
* ICMP transmit source
|
||
* quench entries
|
||
* inserted & removed
|
||
* at the head
|
||
* (see Note #2c)
|
||
*
|
||
* | NextPtr
|
||
* | (see Note #2b)
|
||
* v |
|
||
* |
|
||
* ICMP Transmit ------- ------- v ------- ------- -------
|
||
* Source Quench Pool ---->| |------>| |------>| |------>| |------>| |
|
||
* Pointer | | | | | | | | | |
|
||
* | | | | | | | | | |
|
||
* (see Note #2a) ------- ------- ------- ------- -------
|
||
*
|
||
* | |
|
||
* |<---- Pool of Free ICMP Transmit Source Quench Entries ----->|
|
||
* | (see Note #2) |
|
||
*
|
||
*
|
||
* Argument(s) : perr Pointer to variable that will receive the return error code from this function :
|
||
*
|
||
* NET_ICMP_ERR_NONE ICMP transmit source quench entry
|
||
* successfully allocated & initialized.
|
||
* NET_ICMP_ERR_NONE_AVAIL NO available entries to allocate.
|
||
* NET_ICMP_ERR_INVALID_TYPE ICMP transmit source quench entry is NOT
|
||
* a valid entry type.
|
||
*
|
||
* Return(s) : Pointer to ICMP transmit source quench entry, if NO errors.
|
||
*
|
||
* Pointer to NULL, otherwise.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerTxSrcQuench().
|
||
*
|
||
* Note(s) : (3) (a) ICMP transmit source quench pool is accessed by 'NetICMP_TxSrcQuenchPoolPtr' during
|
||
* execution of
|
||
*
|
||
* (1) NetICMP_Init()
|
||
* (2) NetICMP_HandlerTxSrcQuenchGet()
|
||
* (3) NetICMP_HandlerTxSrcQuenchFree()
|
||
*
|
||
* (b) Since the primary tasks of the network protocol suite are prevented from running
|
||
* concurrently (see 'net.h Note #2'), it is NOT necessary to protect the shared
|
||
* resources of the ICMP transmit source quench pool since no asynchronous access
|
||
* from other network tasks is possible.
|
||
*
|
||
* (4) 'No entry available' case NOT possible during correct operation of the ICMP Transmit
|
||
* Source Quench List. However, the 'else' case is included as an extra precaution in the
|
||
* case that the ICMP Transmit Source Quench List is incorrectly modified &/or corrupted.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static NET_ICMP_TX_SRC_QUENCH *NetICMP_HandlerTxSrcQuenchGet (NET_ERR *perr)
|
||
{
|
||
#if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
NET_ICMP_TX_SRC_QUENCH *ptx_src_quench;
|
||
NET_ERR stat_err;
|
||
|
||
|
||
/* ---------- GET ICMP TX SRC QUENCH ---------- */
|
||
if (NetICMP_TxSrcQuenchPoolPtr != (NET_ICMP_TX_SRC_QUENCH *)0) { /* If ICMP tx src quench pool NOT empty, */
|
||
/* ... get tx src quench entry from pool. */
|
||
ptx_src_quench = (NET_ICMP_TX_SRC_QUENCH *)NetICMP_TxSrcQuenchPoolPtr;
|
||
NetICMP_TxSrcQuenchPoolPtr = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench->NextPtr;
|
||
|
||
/* If ICMP Tx Src Quench List NOT empty, .. */
|
||
} else if (NetICMP_TxSrcQuenchListTail != (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
/* ... get tx src quench entry from list tail. */
|
||
ptx_src_quench = (NET_ICMP_TX_SRC_QUENCH *)NetICMP_TxSrcQuenchListTail;
|
||
NetICMP_HandlerTxSrcQuenchRemove(ptx_src_quench);
|
||
ptx_src_quench = (NET_ICMP_TX_SRC_QUENCH *)NetICMP_TxSrcQuenchPoolPtr;
|
||
NetICMP_TxSrcQuenchPoolPtr = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench->NextPtr;
|
||
|
||
|
||
} else { /* Else none avail, rtn err (see Note #4). */
|
||
NET_CTR_ERR_INC(NetICMP_ErrNoneAvailCtr);
|
||
*perr = NET_ICMP_ERR_NONE_AVAIL;
|
||
return ((NET_ICMP_TX_SRC_QUENCH *)0);
|
||
|
||
}
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------- VALIDATE ICMP TX SRC QUENCH -------- */
|
||
if (ptx_src_quench->Type != NET_ICMP_TYPE_TX_SRC_QUENCH) {
|
||
NetICMP_HandlerTxSrcQuenchDiscard(ptx_src_quench);
|
||
NET_CTR_ERR_INC(NetICMP_ErrInvalidTypeCtr);
|
||
*perr = NET_ICMP_ERR_INVALID_TYPE;
|
||
return ((NET_ICMP_TX_SRC_QUENCH *)0);
|
||
}
|
||
#endif
|
||
|
||
/* --------- INIT ICMP TX SRC QUENCH ---------- */
|
||
NetICMP_HandlerTxSrcQuenchClr(ptx_src_quench);
|
||
DEF_BIT_SET(ptx_src_quench->Flags, NET_ICMP_FLAG_USED); /* Set entry as used. */
|
||
|
||
/* --- UPDATE ICMP TX SRC QUENCH POOL STATS --- */
|
||
NetStat_PoolEntryUsedInc(&NetICMP_TxSrcQuenchPoolStat, &stat_err);
|
||
|
||
*perr = NET_ICMP_ERR_NONE;
|
||
|
||
return (ptx_src_quench); /* ---------- RTN ICMP TX SRC QUENCH ---------- */
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchFree()
|
||
*
|
||
* Description : (1) Free an ICMP transmit source quench entry :
|
||
*
|
||
* (a) Clear ICMP transmit source quench entry controls
|
||
* (b) Free ICMP transmit source quench entry back to pool
|
||
* (c) Update ICMP transmit source quench pool statistics
|
||
*
|
||
*
|
||
* Argument(s) : ptx_src_quench Pointer to an ICMP transmit source quench entry.
|
||
* -------------- Argument validated in NetICMP_HandlerTxSrcQuenchClrList(),
|
||
* NetICMP_HandlerTxSrcQuenchRemove().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerTxSrcQuenchClrList(),
|
||
* NetICMP_HandlerTxSrcQuenchRemove().
|
||
*
|
||
* Note(s) : (2) #### To prevent freeing an ICMP transmit source quench entry already freed via
|
||
* previous ICMP transmit source quench free, NetICMP_HandlerTxSrcQuenchFree()
|
||
* checks the ICMP transmit source quench entry's 'USED' flag BEFORE freeing the
|
||
* ICMP transmit source quench entry.
|
||
*
|
||
* This prevention is only best-effort since any invalid duplicate ICMP transmit
|
||
* source quench frees MAY be asynchronous to potentially valid ICMP transmit
|
||
* source quench gets. Thus the invalid ICMP transmit source quench free(s)
|
||
* MAY corrupt the ICMP transmit source quench entry's valid operation(s).
|
||
*
|
||
* However, since the primary tasks of the network protocol suite are prevented
|
||
* from running concurrently (see 'net.h Note #2'), it is NOT necessary to protect
|
||
* ICMP resources from possible corruption since no asynchronous access from other
|
||
* network tasks is possible.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchFree (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench)
|
||
{
|
||
#if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \
|
||
(NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
CPU_BOOLEAN used;
|
||
#endif
|
||
NET_ERR err;
|
||
|
||
|
||
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
|
||
/* ------------------- VALIDATE TYPE ------------------ */
|
||
if (ptx_src_quench->Type != NET_ICMP_TYPE_TX_SRC_QUENCH) {
|
||
NetICMP_HandlerTxSrcQuenchDiscard(ptx_src_quench);
|
||
NET_CTR_ERR_INC(NetICMP_ErrInvalidTypeCtr);
|
||
return;
|
||
}
|
||
/* --------- VALIDATE ICMP TX SRC QUENCH USED --------- */
|
||
used = DEF_BIT_IS_SET(ptx_src_quench->Flags, NET_ICMP_FLAG_USED);
|
||
if (used != DEF_YES) { /* If ICMP tx src quench NOT used, ... */
|
||
NET_CTR_ERR_INC(NetICMP_ErrNotUsedCtr);
|
||
return; /* ... rtn but do NOT free (see Note #2). */
|
||
}
|
||
#endif
|
||
|
||
/* -------------- CLR ICMP TX SRC QUENCH -------------- */
|
||
DEF_BIT_CLR(ptx_src_quench->Flags, NET_ICMP_FLAG_USED); /* Set ICMP tx src quench entry as NOT used. */
|
||
#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED)
|
||
NetICMP_HandlerTxSrcQuenchClr(ptx_src_quench);
|
||
#endif
|
||
|
||
/* ------------- FREE ICMP TX SRC QUENCH -------------- */
|
||
ptx_src_quench->NextPtr = (void *)NetICMP_TxSrcQuenchPoolPtr;
|
||
NetICMP_TxSrcQuenchPoolPtr = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench;
|
||
|
||
/* ------- UPDATE ICMP TX SRC QUENCH POOL STATS ------- */
|
||
NetStat_PoolEntryUsedDec(&NetICMP_TxSrcQuenchPoolStat, &err);
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchRemove()
|
||
*
|
||
* Description : (1) Remove an ICMP transmit source quench entry from the ICMP Transmit Source Quench List :
|
||
*
|
||
* (a) Remove ICMP transmit source quench entry from list
|
||
* (b) Free ICMP transmit source quench entry back to pool
|
||
*
|
||
*
|
||
* Argument(s) : ptx_src_quench Pointer to an ICMP transmit source quench entry.
|
||
* -------------- Argument validated in NetICMP_HandlerTxSrcQuenchGet().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerTxSrcQuenchGet().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchRemove (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench)
|
||
{
|
||
/* ------- REMOVE ICMP TX SRC QUENCH FROM LIST -------- */
|
||
NetICMP_HandlerTxSrcQuenchUnlink(ptx_src_quench);
|
||
/* ------------- FREE ICMP TX SRC QUENCH -------------- */
|
||
NetICMP_HandlerTxSrcQuenchFree(ptx_src_quench);
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchInsert()
|
||
*
|
||
* Description : Insert an ICMP transmit source quench entry into the ICMP Transmit Source Quench List at
|
||
* the head of the list.
|
||
*
|
||
* Argument(s) : ptx_src_quench Pointer to an ICMP transmit source quench entry.
|
||
* -------------- Argument checked in NetICMP_HandlerTxSrcQuench().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerTxSrcQuench().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchInsert (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench)
|
||
{
|
||
ptx_src_quench->PrevPtr = (void *)0;
|
||
ptx_src_quench->NextPtr = (void *)NetICMP_TxSrcQuenchListHead;
|
||
|
||
if (NetICMP_TxSrcQuenchListHead != (NET_ICMP_TX_SRC_QUENCH *)0) { /* If list NOT empty, insert before head. */
|
||
NetICMP_TxSrcQuenchListHead->PrevPtr = (void *)ptx_src_quench;
|
||
} else { /* Else add first entry to list. */
|
||
NetICMP_TxSrcQuenchListTail = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench;
|
||
}
|
||
NetICMP_TxSrcQuenchListHead = ptx_src_quench; /* Insert entry @ list head. */
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchUnlink()
|
||
*
|
||
* Description : Unlink an ICMP transmit source quench entry from the ICMP Transmit Source Quench List.
|
||
*
|
||
* Argument(s) : ptx_src_quench Pointer to an ICMP transmit source quench entry.
|
||
* -------------- Argument validated in NetICMP_HandlerTxSrcQuenchRemove().
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerTxSrcQuenchRemove().
|
||
*
|
||
* Note(s) : (1) (a) Since NetICMP_HandlerTxSrcQuenchUnlink() called ONLY to remove & free entries from
|
||
* list tail, it is NOT necessary to implement unlink to remove entry from any position
|
||
* in the list. However, unlink from any position in the list implemented for correctness
|
||
* & completeness.
|
||
*
|
||
* (b) For a similar reason, it is NOT necessary to clear the entry's previous & next pointers.
|
||
* However, pointers cleared to NULL shown for correctness & completeness.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED)
|
||
static void NetICMP_HandlerTxSrcQuenchUnlink (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench)
|
||
{
|
||
NET_ICMP_TX_SRC_QUENCH *pentry_prev;
|
||
NET_ICMP_TX_SRC_QUENCH *pentry_next;
|
||
|
||
/* --- UNLINK ICMP TX SRC QUENCH FROM LIST ---- */
|
||
pentry_prev = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench->PrevPtr;
|
||
pentry_next = (NET_ICMP_TX_SRC_QUENCH *)ptx_src_quench->NextPtr;
|
||
/* Point prev entry to next entry. */
|
||
if (pentry_prev != (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
pentry_prev->NextPtr = (void *)pentry_next;
|
||
} else {
|
||
NetICMP_TxSrcQuenchListHead = (NET_ICMP_TX_SRC_QUENCH *)pentry_next;
|
||
}
|
||
/* Point next entry to prev entry. */
|
||
if (pentry_next != (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
pentry_next->PrevPtr = (void *)pentry_prev;
|
||
} else {
|
||
NetICMP_TxSrcQuenchListTail = (NET_ICMP_TX_SRC_QUENCH *)pentry_prev;
|
||
}
|
||
|
||
#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) /* Clr ICMP src quench ptrs (see Note #1b). */
|
||
ptx_src_quench->PrevPtr = (void *)0;
|
||
ptx_src_quench->NextPtr = (void *)0;
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* NetICMP_HandlerTxSrcQuenchDiscard()
|
||
*
|
||
* Description : (1) Discard an invalid/corrupted ICMP transmit source quench entry :
|
||
*
|
||
* (a) Discard ICMP transmit source quench entry from available pool See Note #2
|
||
* (b) Update ICMP transmit source quench pool statistics
|
||
*
|
||
* (2) Assumes ICMP transmit source quench entry is invalid/corrupt & MUST be removed.
|
||
* ICMP transmit source quench entry removed simply by NOT returning the entry back
|
||
* to the ICMP transmit source quench pool.
|
||
*
|
||
*
|
||
* Argument(s) : pcache Pointer to an invalid/corrupted ICMP transmit source quench entry.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : NetICMP_HandlerTxSrcQuenchGet(),
|
||
* NetICMP_HandlerTxSrcQuenchFree().
|
||
*
|
||
* Note(s) : none.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if ((NET_ICMP_CFG_TX_SRC_QUENCH_EN == DEF_ENABLED) && \
|
||
(NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
|
||
static void NetICMP_HandlerTxSrcQuenchDiscard (NET_ICMP_TX_SRC_QUENCH *ptx_src_quench)
|
||
{
|
||
#if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
|
||
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
|
||
CPU_SR cpu_sr;
|
||
#endif
|
||
NET_ERR stat_err;
|
||
|
||
/* ------------ DISCARD ICMP TX SRC QUENCH ------------ */
|
||
if (ptx_src_quench == (NET_ICMP_TX_SRC_QUENCH *)0) {
|
||
NET_CTR_ERR_INC(NetICMP_ErrNullPtrCtr);
|
||
return;
|
||
}
|
||
|
||
/* --------------- UPDATE DISCARD STATS --------------- */
|
||
NetStat_PoolEntryLostInc(&NetICMP_TxSrcQuenchPoolStat, &stat_err);
|
||
}
|
||
#endif
|
||
|