6283 lines
294 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
* 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 IP LAYER
* (INTERNET PROTOCOL)
*
* Filename : net_ip.c
* Version : V1.89
* Programmer(s) : ITJ
*********************************************************************************************************
* Note(s) : (1) Supports Internet Protocol as described in RFC #791, also known as IPv4, with the
* following restrictions/constraints :
*
* (a) ONLY supports a single network interface/ RFC # 791, Section 2.3
* host IP address 'Addressing'
*
* (b) ONLY supports a single default gateway RFC #1122, Section 3.3.1
*
* (c) IP forwarding/routing NOT supported RFC #1122, Sections 3.3.1,
* 3.3.4 & 3.3.5
*
* (d) IP multicasting NOT supported RFC #1122, Section 3.3.7
*
* (e) Transmit fragmentation NOT currently supported RFC # 791, Section 2.3
* 'Fragmentation &
* Reassembly'
* (f) IP Security options NOT currently supported RFC #1108
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define NET_IP_MODULE
#include <net.h>
/*$PAGE*/
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/*$PAGE*/
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
/* -------- VALIDATE RX DATAGRAMS --------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetIP_RxPktValidateBuf (NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
#endif
static void NetIP_RxPktValidate (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_HDR *pip_hdr,
NET_ERR *perr);
static void NetIP_RxPktValidateOpt (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_HDR *pip_hdr,
CPU_INT08U ip_hdr_len_size,
NET_ERR *perr);
static CPU_BOOLEAN NetIP_RxPktValidateOptRoute (CPU_INT08U *popts,
CPU_INT08U opt_list_len_rem,
CPU_INT08U *popt_len,
NET_ERR *perr);
static CPU_BOOLEAN NetIP_RxPktValidateOptTS (CPU_INT08U *popts,
CPU_INT08U opt_list_len_rem,
CPU_INT08U *popt_len,
NET_ERR *perr);
/* ------------ REASM RX FRAGS ------------ */
static NET_BUF *NetIP_RxPktFragReasm (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_HDR *pip_hdr,
NET_ERR *perr);
static NET_BUF *NetIP_RxPktFragListAdd (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT16U frag_ip_flags,
CPU_INT16U frag_offset,
CPU_INT16U frag_size,
NET_ERR *perr);
static NET_BUF *NetIP_RxPktFragListInsert (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT16U frag_ip_flags,
CPU_INT16U frag_offset,
CPU_INT16U frag_size,
NET_BUF *pfrag_list,
NET_ERR *perr);
static void NetIP_RxPktFragListRemove (NET_BUF *pfrag_list,
CPU_BOOLEAN tmr_free);
static void NetIP_RxPktFragListDiscard (NET_BUF *pfrag_list,
CPU_BOOLEAN tmr_free,
NET_ERR *perr);
static void NetIP_RxPktFragListUpdate (NET_BUF *pfrag_list,
NET_BUF_HDR *pfrag_list_buf_hdr,
CPU_INT16U frag_ip_flags,
CPU_INT16U frag_offset,
CPU_INT16U frag_size,
NET_ERR *perr);
static NET_BUF *NetIP_RxPktFragListChkComplete(NET_BUF *pfrag_list,
NET_BUF_HDR *pfrag_list_buf_hdr,
NET_ERR *perr);
static void NetIP_RxPktFragTimeout (void *pfrag_list_timeout);
/* ---------- DEMUX RX DATAGRAMS ---------- */
static void NetIP_RxPktDemuxDatagram (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
static void NetIP_RxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr);
/*$PAGE*/
/* ----------- VALIDATE TX PKTS ----------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetIP_TxPktValidate (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
void *popts,
NET_ERR *perr);
static void NetIP_TxPktValidateOpt (void *popts,
NET_ERR *perr);
static void NetIP_TxPktValidateOptRouteTS (void *popt_route_ts,
CPU_INT08U *popt_len,
void **popt_next,
NET_ERR *perr);
#endif
/* -------------- TX IP PKTS -------------- */
static void NetIP_TxPkt (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
void *popts,
NET_ERR *perr);
static CPU_INT08U NetIP_TxPktPrepareOpt (void *popts,
CPU_INT08U *popt_hdr,
NET_ERR *perr);
static void NetIP_TxPktPrepareOptRoute (void *popts,
CPU_INT08U *popt_hdr,
CPU_INT08U *popt_len,
void **popt_next,
NET_ERR *perr);
static void NetIP_TxPktPrepareOptTS (void *popts,
CPU_INT08U *popt_hdr,
CPU_INT08U *popt_len,
void **popt_next,
NET_ERR *perr);
static void NetIP_TxPktPrepareOptTSRoute (void *popts,
CPU_INT08U *popt_hdr,
CPU_INT08U *popt_len,
void **popt_next,
NET_ERR *perr);
static void NetIP_TxPktPrepareHdr (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT16U ip_hdr_len_tot,
CPU_INT08U ip_opt_len_tot,
CPU_INT16U protocol_ix,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
CPU_INT32U *pip_hdr_opts,
NET_ERR *perr);
/* ------------ TX IP DATAGRAMS ----------- */
static void NetIP_TxPktDatagram (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
static void NetIP_TxPktDatagramNextHopSel (NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
static void NetIP_TxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr);
/*$PAGE*/
/* ------------ RE-TX IP PKTS ------------- */
static void NetIP_ReTxPkt (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
static void NetIP_ReTxPktPrepareHdr (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
/*
*********************************************************************************************************
* LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_Init()
*
* Description : (1) Initialize Internet Protocol Layer :
*
* (a) Initialize IP pointers & counters
* (b) Initialize IP 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) : none.
*********************************************************************************************************
*/
void NetIP_Init (void)
{
/* ---------------- INIT IP PTRS/CTRS ----------------- */
/* Ptrs used to update Rx Frag Reasm Lists. */
NetIP_FragReasmListsHead = (NET_BUF *)0;
NetIP_FragReasmListsTail = (NET_BUF *)0;
NetIP_TxIDCtr = NET_IP_ID_INIT;
/* ------------- INIT IP STAT & ERR CTRS -------------- */
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
NetIP_StatRxPktCtr = 0;
NetIP_StatRxDatagramProcessedCtr = 0;
NetIP_StatRxDestLocalCtr = 0;
NetIP_StatRxDestBroadcastCtr = 0;
NetIP_StatRxFragCtr = 0;
NetIP_StatRxFragDatagramReasmCtr = 0;
NetIP_StatTxDatagramCtr = 0;
NetIP_StatTxDestLocalCtr = 0;
NetIP_StatTxDestBroadcastCtr = 0;
#endif
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
NetIP_ErrNullPtrCtr = 0;
NetIP_ErrCfgAddrThisHostCtr = 0;
NetIP_ErrCfgAddrDfltGatewayCtr = 0;
NetIP_ErrRxHdrVerCtr = 0;
NetIP_ErrRxHdrLenCtr = 0;
NetIP_ErrRxHdrTotLenCtr = 0;
NetIP_ErrRxHdrFlagsCtr = 0;
NetIP_ErrRxHdrFragCtr = 0;
NetIP_ErrRxHdrProtocolCtr = 0;
NetIP_ErrRxHdrChkSumCtr = 0;
NetIP_ErrRxHdrAddrSrcCtr = 0;
NetIP_ErrRxHdrOptsCtr = 0;
NetIP_ErrRxHdrOptsBufNoneAvailCtr = 0;
NetIP_ErrRxHdrOptsBufWrCtr = 0;
NetIP_ErrRxDestCtr = 0;
NetIP_ErrRxDestBroadcastCtr = 0;
NetIP_ErrRxFragSizeCtr = 0;
NetIP_ErrRxFragDiscardedCtr = 0;
NetIP_ErrRxFragDatagramDiscardedCtr = 0;
NetIP_ErrRxFragDatagramTimeoutCtr = 0;
NetIP_ErrRxPktDiscardedCtr = 0;
NetIP_ErrTxProtocolCtr = 0;
NetIP_ErrTxOptTypeCtr = 0;
NetIP_ErrTxDestCtr = 0;
NetIP_ErrTxPktDiscardedCtr = 0;
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
NetIP_ErrRxInvalidBufIxCtr = 0;
NetIP_ErrRxHdrDataLenCtr = 0;
NetIP_ErrRxFragFlagsCtr = 0;
NetIP_ErrRxFragOffsetCtr = 0;
NetIP_ErrTxInvalidBufIxCtr = 0;
NetIP_ErrTxHdrTOS_Ctr = 0;
NetIP_ErrTxHdrDataLenCtr = 0;
NetIP_ErrTxHdrAddrSrcCtr = 0;
NetIP_ErrTxHdrAddrDestCtr = 0;
NetIP_ErrTxHdrFlagsCtr = 0;
NetIP_ErrTxHdrOptLenCtr = 0;
NetIP_ErrTxHdrOptCfgCtr = 0;
#endif
#if 0 /* #### NOT currently implemented. */
/* See 'net_ip.c Note #1e'. */
NetIP_ErrTxFragDiscardedCtr = 0;
NetIP_ErrTxFragDiscardedDontFragCtr = 0;
#endif
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_CfgAddrThisHost()
*
* Description : (1) Configure this host's IP address :
*
* (a) Validate this host's IP address & subnet mask
* (b) Configure this host's IP address, subnet mask, & subnet
*
*
* Argument(s) : addr_host Desired IP address for this host (see Note #2).
*
* addr_subnet_mask Desired IP address subnet mask for this host (see Note #2).
*
* Return(s) : DEF_OK, if valid host IP address & subnet mask configured.
*
* DEF_FAIL, otherwise.
*
* Caller(s) : Net_InitDflt() [see Note #3],
* Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (2) Host IP addresses MUST be in host-order.
*
* (3) The default initialization configuration by Net_InitDflt() is invalid & forces the
* developer or higher-layer protocol application to configure a valid IP address &
* subnet mask.
*********************************************************************************************************
*/
CPU_BOOLEAN NetIP_CfgAddrThisHost (NET_IP_ADDR addr_host,
NET_IP_ADDR addr_subnet_mask)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
CPU_BOOLEAN valid_addr;
CPU_BOOLEAN valid_cfg;
valid_addr = NetIP_IsValidAddrThisHost(addr_host, addr_subnet_mask);
valid_cfg = (valid_addr == DEF_YES) ? DEF_OK : DEF_FAIL;
if (valid_cfg == DEF_OK) {
CPU_CRITICAL_ENTER();
NetIP_AddrThisHost = addr_host;
NetIP_AddrThisHostNetOrder = (NET_IP_ADDR) NET_UTIL_HOST_TO_NET_32(addr_host);
NetIP_AddrThisHostSubnetMask = (NET_IP_ADDR) addr_subnet_mask;
NetIP_AddrThisHostSubnetMaskHost = (NET_IP_ADDR)~addr_subnet_mask;
NetIP_AddrThisHostSubnetNet = addr_host & addr_subnet_mask;
CPU_CRITICAL_EXIT();
} else {
NET_CTR_ERR_INC(NetIP_ErrCfgAddrThisHostCtr);
CPU_CRITICAL_ENTER();
NetIP_AddrThisHost = (NET_IP_ADDR)NET_IP_ADDR_NONE;
NetIP_AddrThisHostNetOrder = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(NET_IP_ADDR_NONE);
NetIP_AddrThisHostSubnetMask = (NET_IP_ADDR)NET_IP_ADDR_NONE;
NetIP_AddrThisHostSubnetMaskHost = (NET_IP_ADDR)NET_IP_ADDR_NONE;
NetIP_AddrThisHostSubnetNet = (NET_IP_ADDR)NET_IP_ADDR_NONE;
CPU_CRITICAL_EXIT();
}
return (valid_cfg);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_CfgAddrDfltGateway()
*
* Description : (1) Configure this host's default gateway IP address :
*
* (a) Validate this host's default gateway IP address
* (b) Configure this host's default gateway IP address
*
*
* Argument(s) : addr_dflt_gateway Desired IP address for this host's default gateway (see Note #2).
*
* Return(s) : DEF_OK, if valid default gateway IP address configured.
*
* DEF_FAIL, otherwise.
*
* Caller(s) : Net_InitDflt() [see Note #3],
* Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (2) Default gateway address MUST be in host-order.
*
* (3) The default initialization configuration by Net_InitDflt() is invalid & forces the
* developer or higher-layer protocol application to configure a valid default gateway
* IP address.
*
* (4) (a) RFC #1122, Section 3.3.1.1. states that "the host IP layer MUST operate correctly
* in a minimal network environment, and in particular, when there are no gateways".
*
* In other words, a host on an isolated network should be able to correctly operate
* & communicate with all other hosts on its local network without need of a gateway
* or configuration of a gateway.
*
* (b) However, if this host's network interface is a network type (versus a serial
* connection) AND the default gateway is configured with an invalid IP address
* NOT on the local network, then ALL non-local-network destination IP datagrams
* will be discarded at the physical link-layer/network interface.
*********************************************************************************************************
*/
CPU_BOOLEAN NetIP_CfgAddrDfltGateway (NET_IP_ADDR addr_dflt_gateway)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
CPU_BOOLEAN valid_addr;
CPU_BOOLEAN valid_cfg;
valid_addr = NetIP_IsValidAddrHost(addr_dflt_gateway);
valid_cfg = (valid_addr == DEF_YES) ? DEF_OK : DEF_FAIL;
if (valid_cfg == DEF_OK) {
CPU_CRITICAL_ENTER();
NetIP_AddrDfltGateway = (NET_IP_ADDR)addr_dflt_gateway;
CPU_CRITICAL_EXIT();
} else {
NET_CTR_ERR_INC(NetIP_ErrCfgAddrDfltGatewayCtr);
CPU_CRITICAL_ENTER();
NetIP_AddrDfltGateway = (NET_IP_ADDR)NET_IP_ADDR_NONE;
CPU_CRITICAL_EXIT();
}
return (valid_cfg);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_CfgFragReasmTimeout()
*
* Description : Configure IP fragment reassembly timeout.
*
* (1) IP fragment reassembly timeout is the maximum time allowed between received IP fragments
* from the same IP datagram.
*
*
* Argument(s) : timeout_sec Desired value for IP fragment reassembly timeout (in seconds).
*
* Return(s) : DEF_OK, IP fragment reassembly timeout 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) : (2) Timeout in seconds converted to 'NET_TMR_TICK' ticks in order to pre-compute initial
* timeout value in 'NET_TMR_TICK' ticks.
*********************************************************************************************************
*/
CPU_BOOLEAN NetIP_CfgFragReasmTimeout (CPU_INT08U timeout_sec)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_TMR_TICK tick;
if (timeout_sec < NET_IP_FRAG_REASM_TIMEOUT_MIN_SEC) {
timeout_sec = NET_IP_FRAG_REASM_TIMEOUT_MIN_SEC;
}
if (timeout_sec > NET_IP_FRAG_REASM_TIMEOUT_MAX_SEC) {
timeout_sec = NET_IP_FRAG_REASM_TIMEOUT_MAX_SEC;
}
tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
CPU_CRITICAL_ENTER();
NetIP_FragReasmTimeout_sec = timeout_sec;
NetIP_FragReasmTimeout_tick = tick;
CPU_CRITICAL_EXIT();
return (DEF_OK);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_GetAddrThisHost()
*
* Description : Get this host's IP address.
*
* Argument(s) : none.
*
* Return(s) : This host's IP address in host-order.
*
* Caller(s) : Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : none.
*********************************************************************************************************
*/
NET_IP_ADDR NetIP_GetAddrThisHost (void)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_IP_ADDR addr;
CPU_CRITICAL_ENTER();
addr = NetIP_AddrThisHost;
CPU_CRITICAL_EXIT();
return (addr);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_GetAddrDfltGateway()
*
* Description : Get this host's default gateway IP address.
*
* Argument(s) : none.
*
* Return(s) : This host's default gateway IP address in host-order.
*
* Caller(s) : Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : none.
*********************************************************************************************************
*/
NET_IP_ADDR NetIP_GetAddrDfltGateway (void)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_IP_ADDR addr;
CPU_CRITICAL_ENTER();
addr = NetIP_AddrDfltGateway;
CPU_CRITICAL_EXIT();
return (addr);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_GetAddrStrThisHost()
*
* Description : Get this host's IP address as an ASCII string.
*
* Argument(s) : paddr Pointer to an ASCII character array that will receive the return IP address
* ASCII string from this function (see Note #1).
*
* Return(s) : Pointer to this host's IP address string, if NO errors.
*
* Pointer to NULL, otherwise.
*
* Caller(s) : Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (1) The size of the ASCII character array that will receive the return IP address ASCII
* string MUST be greater than or equal to NET_ASCII_LEN_MAX_ADDR_IP.
*
* See also 'net_ascii.c NetASCII_IP_to_Str() Note #2'.
*********************************************************************************************************
*/
CPU_CHAR *NetIP_GetAddrStrThisHost (CPU_CHAR *paddr)
{
NET_IP_ADDR addr;
NET_ERR err;
addr = NetIP_GetAddrThisHost(); /* Get this host's IP addr. */
NetASCII_IP_to_Str(addr, paddr, DEF_NO, &err); /* Conv IP addr to IP addr str. */
if (err != NET_ASCII_ERR_NONE) { /* On any str err, ... */
*paddr = (CPU_CHAR )0; /* ... rtn NULL addr ... */
return ((CPU_CHAR *)0); /* ... & rtn NULL. */
}
return (paddr);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_GetAddrStrDfltGateway()
*
* Description : Get this host's default gateway IP address as an ASCII string.
*
* Argument(s) : paddr Pointer to an ASCII character array that will receive the return IP address
* ASCII string from this function (see Note #1).
*
* Return(s) : Pointer to this host's default gateway IP address string, if NO errors.
*
* Pointer to NULL, otherwise.
*
* Caller(s) : Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (1) The size of the ASCII character array that will receive the return IP address ASCII
* string MUST be greater than or equal to NET_ASCII_LEN_MAX_ADDR_IP.
*
* See also 'net_ascii.c NetASCII_IP_to_Str() Note #2'.
*********************************************************************************************************
*/
CPU_CHAR *NetIP_GetAddrStrDfltGateway (CPU_CHAR *paddr)
{
NET_IP_ADDR addr;
NET_ERR err;
addr = NetIP_GetAddrDfltGateway(); /* Get this host's dflt gateway IP addr. */
NetASCII_IP_to_Str(addr, paddr, DEF_NO, &err); /* Conv IP addr to IP addr str. */
if (err != NET_ASCII_ERR_NONE) { /* On any str err, ... */
*paddr = (CPU_CHAR )0; /* ... rtn NULL addr ... */
return ((CPU_CHAR *)0); /* ... & rtn NULL. */
}
return (paddr);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_IsValidAddrHost()
*
* Description : (1) Validate an IP host address which MUST NOT be one of the following :
*
* (a) This Host RFC #1122, Section 3.2.1.3.(a)
* (b) Limited Broadcast RFC #1122, Section 3.2.1.3.(c)
* (c) Localhost RFC #1122, Section 3.2.1.3.(g)
* (d) Specified Host RFC #1122, Section 3.2.1.3.(b)
* (e) Directed Broadcast RFC #1122, Section 3.2.1.3.(d)
*
* (2) ONLY validates typical IP host addresses, since 'This Host' & 'Specified Host' IP host
* addresses are ONLY valid during a host's initialization (see Notes #1a & #1d). This
* function CANNOT be used to validate host addresses if any 'This Host' or 'Specified Host'
* host addresses are passed.
*
*
* Argument(s) : addr_host IP host address to validate.
*
* Return(s) : DEF_YES, if IP host address valid.
*
* DEF_NO, otherwise.
*
* Caller(s) : various.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (3) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
*********************************************************************************************************
*/
/*$PAGE*/
CPU_BOOLEAN NetIP_IsValidAddrHost (NET_IP_ADDR addr_host)
{
CPU_BOOLEAN valid;
valid = DEF_YES;
/* -------------- VALIDATE HOST ADDR -------------- */
/* Chk invalid 'This Host' (see Note #1a). */
if (addr_host == NET_IP_ADDR_THIS_HOST) {
valid = DEF_NO;
/* Chk invalid limited broadcast (see Note #1b). */
} else if (addr_host == NET_IP_ADDR_BROADCAST) {
valid = DEF_NO;
/* Chk invalid localhost (see Note #1c). */
} else if ((addr_host & NET_IP_ADDR_LOCAL_HOST_MASK) == NET_IP_ADDR_LOCAL_HOST) {
valid = DEF_NO;
} else if ((addr_host & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
/* Chk invalid Class-A specified (see Note #1d). */
if ((addr_host & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
valid = DEF_NO;
}
/* Chk invalid Class-A broadcast (see Note #1e). */
if ((addr_host & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
valid = DEF_NO;
}
} else if ((addr_host & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
/* Chk invalid Class-B specified (see Note #1d). */
if ((addr_host & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
valid = DEF_NO;
}
/* Chk invalid Class-B broadcast (see Note #1e). */
if ((addr_host & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
valid = DEF_NO;
}
} else if ((addr_host & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
/* Chk invalid Class-C specified (see Note #1d). */
if ((addr_host & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
valid = DEF_NO;
}
/* Chk invalid Class-C broadcast (see Note #1e). */
if ((addr_host & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
valid = DEF_NO;
}
} else { /* Invalid addr class (see Note #3). */
valid = DEF_NO;
}
return (valid);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_IsValidAddrThisHost()
*
* Description : (1) Validate this host's IP address which MUST NOT be one of the following :
*
* (a) This Host RFC #1122, Section 3.2.1.3.(a)
* (b) Limited Broadcast RFC #1122, Section 3.2.1.3.(c)
* (c) Localhost RFC #1122, Section 3.2.1.3.(g)
* (d) Specified Host RFC #1122, Section 3.2.1.3.(b)
* (e) Directed Broadcast RFC #1122, Section 3.2.1.3.(d)
* (f) Subnet Broadcast RFC #1122, Section 3.2.1.3.(e)
*
* (2) ONLY validates this host's IP address, since 'This Host' & 'Specified Host' IP host
* addresses are ONLY valid during a host's initialization (see Notes #1a & #1d). This
* function CANNOT be used to validate host addresses if any 'This Host' or 'Specified Host'
* host addresses are passed.
*
*
* Argument(s) : addr_host IP host address to validate.
*
* addr_subnet_mask IP subnet mask.
*
* Return(s) : DEF_YES, if this host's IP address valid.
*
* DEF_NO, otherwise.
*
* Caller(s) : NetIP_CfgAddrThisHost().
*
* This function is an INTERNAL network protocol suite function & SHOULD NOT be called by
* application function(s).
*
* Note(s) : (3) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
*********************************************************************************************************
*/
CPU_BOOLEAN NetIP_IsValidAddrThisHost (NET_IP_ADDR addr_host,
NET_IP_ADDR addr_subnet_mask)
{
CPU_BOOLEAN valid_host;
CPU_BOOLEAN valid_mask;
CPU_BOOLEAN valid;
valid_host = NetIP_IsValidAddrHost(addr_host);
valid_mask = NetIP_IsValidAddrSubnetMask(addr_subnet_mask);
valid = ((valid_host == DEF_YES) &&
(valid_mask == DEF_YES)) ? DEF_YES : DEF_NO;
if (valid == DEF_YES) {
/* Chk invalid subnet specified (see Note #1d). */
if ((addr_host & addr_subnet_mask) == NET_IP_ADDR_THIS_HOST) {
valid = DEF_NO;
}
/* Chk invalid subnet broadcast (see Note #1f). */
if ((addr_host & addr_subnet_mask) == NET_IP_ADDR_BROADCAST) {
valid = DEF_NO;
}
}
return (valid);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_IsValidAddrSubnetMask()
*
* Description : (1) Validate an IP subnet mask :
*
* (a) RFC #1122, Section 3.2.1.3 states that ... :
*
* (1) "IP addresses are not permitted to have the value 0 or -1 for any of the ...
* <Subnet-number> fields" ...
* (2) "This implies that each of these fields will be at least two bits long."
*
* (b) RFC #950, Section 2.1 'Special Addresses' reiterates that "the values of all
* zeros and all ones in the subnet field should not be assigned to actual
* (physical) subnets".
*
* (c) RFC #950, Section 2.1 also states that "the bits that identify the subnet ...
* need not be adjacent in the address. However, we recommend that the subnet
* bits be contiguous and located as the most significant bits of the local
* address".
*
* See also 'net_ip.h IP ADDRESS DEFINES Note #3'.
*
* Argument(s) : addr_subnet_mask IP subnet mask to validate.
*
* Return(s) : DEF_YES, if IP subnet mask valid.
*
* DEF_NO, otherwise.
*
* Caller(s) : NetIP_IsValidAddrThisHost().
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_BOOLEAN NetIP_IsValidAddrSubnetMask (NET_IP_ADDR addr_subnet_mask)
{
CPU_BOOLEAN valid;
NET_IP_ADDR mask;
CPU_INT08U mask_size;
CPU_INT08U mask_nbr_one_bits;
CPU_INT08U mask_nbr_one_bits_min;
CPU_INT08U mask_nbr_one_bits_max;
CPU_INT08U i;
/* ------------- VALIDATE SUBNET MASK ------------- */
/* Chk invalid subnet class (see Note #1c). */
if ((addr_subnet_mask & NET_IP_ADDR_CLASS_SUBNET_MASK) == NET_IP_ADDR_NONE) {
valid = DEF_NO;
} else { /* Chk invalid subnet mask (see Notes #1a & #1b). */
mask_size = sizeof(addr_subnet_mask) * DEF_OCTET_NBR_BITS;
mask = DEF_BIT_00;
mask_nbr_one_bits = 0;
for (i = 0; i < mask_size; i++) { /* Calc nbr subnet bits. */
if (addr_subnet_mask & mask) {
mask_nbr_one_bits++;
}
mask <<= 1;
}
mask_nbr_one_bits_min = 2; /* See Note #1a2. */
mask_nbr_one_bits_max = mask_size - mask_nbr_one_bits_min;
/* Chk invalid nbr subnet bits (see Note #1a2). */
if (mask_nbr_one_bits < mask_nbr_one_bits_min) {
valid = DEF_NO;
} else if (mask_nbr_one_bits > mask_nbr_one_bits_max) {
valid = DEF_NO;
} else {
valid = DEF_YES;
}
}
return (valid);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_Rx()
*
* Description : (1) Process received datagrams & forward to network protocol layers :
*
* (a) Validate IP packet & options
* (b) Reassemble fragmented datagrams
* (c) Demultiplex datagram to higher-layer protocols
* (d) Update receive statistics
*
* (2) Although IP data units are typically referred to as 'datagrams' (see RFC #791, Section 1.1),
* the term 'IP packet' (see RFC #1983, 'packet') is used for IP Receive until the packet is
* validated, & possibly reassembled, as an IP datagram.
*
*
* Argument(s) : pbuf Pointer to network buffer that received IP packet.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP datagram successfully received & processed.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* ----- RETURNED BY NetIP_RxPktDiscard() : -----
* NET_ERR_RX Receive error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetIF_RxPktFrameDemux(),
* NetIP_TxPktDatagram().
*
* This function is a network protocol suite to network interface (IF) function & SHOULD be
* called only by appropriate network interface function(s).
*
* Note(s) : (3) NetIP_Rx() blocked until network initialization completes.
*
* (4) Since NetIP_RxPktFragReasm() may return a pointer to a different packet buffer (see
* 'NetIP_RxPktFragReasm() Return(s)', 'pbuf_hdr' MUST be reloaded.
*
* (5) (a) For single packet buffer IP datagrams, the datagram length is equal to the IP
* Total Length minus the IP Header Length.
*
* (b) For multiple packet buffer, fragmented IP datagrams, the datagram length is
* equal to the previously calculated total fragment size.
*
* (1) IP datagram length is stored ONLY in the first packet buffer of any
* fragmented packet buffers.
*
* (6) Network buffer already freed by higher layer; only increment error counter.
*********************************************************************************************************
*/
/*$PAGE*/
void NetIP_Rx (NET_BUF *pbuf,
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;
#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) {
NetIP_RxPktDiscard(pbuf, perr);
NET_CTR_ERR_INC(NetIP_ErrNullPtrCtr);
return;
}
#endif
NET_CTR_STAT_INC(NetIP_StatRxPktCtr);
/* ------------------ VALIDATE IP PKT ----------------- */
pbuf_hdr = &pbuf->Hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
NetIP_RxPktValidateBuf(pbuf_hdr, perr); /* Validate rx'd buf. */
switch (*perr) {
case NET_IP_ERR_NONE:
break;
case NET_ERR_INVALID_PROTOCOL:
case NET_BUF_ERR_INVALID_IX:
default:
NetIP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
#endif
pip_hdr = (NET_IP_HDR *)&pbuf->Data[pbuf_hdr->IP_HdrIx];
NetIP_RxPktValidate(pbuf, pbuf_hdr, pip_hdr, perr); /* Validate rx'd pkt. */
/* ------------------- REASM FRAGS -------------------- */
switch (*perr) {
case NET_IP_ERR_NONE:
pbuf = NetIP_RxPktFragReasm(pbuf, pbuf_hdr, pip_hdr, perr);
break;
case NET_IP_ERR_INVALID_VER:
case NET_IP_ERR_INVALID_LEN_HDR:
case NET_IP_ERR_INVALID_LEN_TOT:
case NET_IP_ERR_INVALID_LEN_DATA:
case NET_IP_ERR_INVALID_FLAG:
case NET_IP_ERR_INVALID_FRAG:
case NET_IP_ERR_INVALID_PROTOCOL:
case NET_IP_ERR_INVALID_CHK_SUM:
case NET_IP_ERR_INVALID_ADDR_SRC:
case NET_IP_ERR_INVALID_ADDR_DEST:
case NET_IP_ERR_INVALID_OPT:
case NET_IP_ERR_INVALID_OPT_LEN:
case NET_IP_ERR_INVALID_OPT_NBR:
case NET_IP_ERR_INVALID_OPT_END:
case NET_IP_ERR_INVALID_OPT_FLAG:
case NET_IP_ERR_RX_OPT_BUF_NONE_AVAIL:
case NET_IP_ERR_RX_OPT_BUF_WR:
default:
NetIP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/*$PAGE*/
/* -------------- DEMUX DATAGRAM -------------- */
switch (*perr) { /* Chk err from NetIP_RxPktFragReasm(). */
case NET_IP_ERR_RX_FRAG_NONE:
case NET_IP_ERR_RX_FRAG_COMPLETE:
pbuf_hdr = &pbuf->Hdr; /* Reload buf hdr ptr (see Note #4). */
if (*perr == NET_IP_ERR_RX_FRAG_NONE) { /* If pkt NOT frag'd, ... */
pbuf_hdr->IP_DatagramLen = pbuf_hdr->IP_TotLen /* ... calc buf datagram len (see Note #5a). */
- pbuf_hdr->IP_HdrLen;
} else { /* Else set tot frag size ... */
pbuf_hdr->IP_DatagramLen = pbuf_hdr->IP_FragSizeTot; /* ... as datagram len (see Note #5b). */
}
NetIP_RxPktDemuxDatagram(pbuf, pbuf_hdr, perr);
break;
case NET_IP_ERR_RX_FRAG_REASM: /* Frag'd datagram in reasm. */
*perr = NET_IP_ERR_NONE;
return; /* Prevent 'break NOT reachable' compiler warning. */
case NET_IP_ERR_RX_FRAG_DISCARD:
case NET_IP_ERR_RX_FRAG_OFFSET:
case NET_IP_ERR_RX_FRAG_SIZE:
case NET_IP_ERR_RX_FRAG_SIZE_TOT:
case NET_IP_ERR_RX_FRAG_LEN_TOT:
default:
NetIP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ----------------- UPDATE RX STATS ------------------ */
switch (*perr) { /* Chk err from NetIP_RxPktDemuxDatagram(). */
case NET_ICMP_ERR_NONE:
case NET_TCP_ERR_NONE:
case NET_UDP_ERR_NONE:
NET_CTR_STAT_INC(NetIP_StatRxDatagramProcessedCtr);
*perr = NET_IP_ERR_NONE;
break;
case NET_ERR_RX:
NET_CTR_ERR_INC(NetIP_ErrRxPktDiscardedCtr); /* See Note #6. */
return; /* Prevent 'break NOT reachable' compiler warning. */
case NET_ERR_INIT_INCOMPLETE:
case NET_ERR_INVALID_PROTOCOL:
default:
NetIP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_Tx()
*
* Description : (1) Prepare & transmit packets from transport protocol layers to network interface layer :
*
* (a) Validate transmit packet
* (b) Prepare & transmit packet datagram
* (c) Update transmit statistics
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit IP packet.
*
* addr_src Source IP address.
*
* addr_dest Destination IP address.
*
* 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 RFC #1122, Section 3.2.1.7) :
*
* NET_IP_HDR_TTL_MIN 1 minimum TTL transmit value
* NET_IP_HDR_TTL_MAX 255 maximum TTL transmit value
* NET_IP_HDR_TTL_DFLT default TTL transmit value
* NET_IP_HDR_TTL_NONE 0 replace with default TTL
*
* 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.c Note #1f').
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP datagram(s) successfully prepared & transmitted
* to network interface layer.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* ------- RETURNED BY NetIP_TxPktDiscard() : -------
* NET_ERR_TX Transmit error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetICMP_TxMsgErr(),
* NetICMP_TxMsgReq(),
* NetICMP_TxMsgReply(),
* NetUDP_Tx(),
* NetTCP_TxPkt().
*
* This function is an INTERNAL network protocol suite function & SHOULD NOT be called by
* application function(s).
*
* Note(s) : (2) NetIP_Tx() blocked until network initialization completes.
*
* (3) Network buffer already freed by lower layer; only increment error counter.
*********************************************************************************************************
*/
/*$PAGE*/
void NetIP_Tx (NET_BUF *pbuf,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
void *popts,
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;
#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) {
NetIP_TxPktDiscard(pbuf, perr);
NET_CTR_ERR_INC(NetIP_ErrNullPtrCtr);
return;
}
#endif
/* ---------------- VALIDATE TX IP PKT ---------------- */
pbuf_hdr = &pbuf->Hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
NetIP_TxPktValidate(pbuf,
pbuf_hdr,
addr_src,
addr_dest,
TOS,
TTL,
flags,
popts,
perr);
switch (*perr) {
case NET_IP_ERR_NONE:
break;
case NET_ERR_INVALID_PROTOCOL:
case NET_BUF_ERR_INVALID_IX:
case NET_IP_ERR_INVALID_LEN_DATA:
case NET_IP_ERR_INVALID_TOS:
case NET_IP_ERR_INVALID_ADDR_SRC:
case NET_IP_ERR_INVALID_ADDR_DEST:
case NET_IP_ERR_INVALID_FLAG:
case NET_IP_ERR_INVALID_OPT_TYPE:
case NET_IP_ERR_INVALID_OPT_LEN:
case NET_IP_ERR_INVALID_OPT_CFG:
case NET_IP_ERR_INVALID_OPT_ROUTE:
default:
NetIP_TxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
#endif
/*$PAGE*/
/* -------------------- TX IP PKT --------------------- */
NetIP_TxPkt(pbuf,
pbuf_hdr,
addr_src,
addr_dest,
TOS,
TTL,
flags,
popts,
perr);
/* ----------------- UPDATE TX STATS ------------------ */
switch (*perr) {
case NET_IP_ERR_NONE:
case NET_IF_ERR_NONE:
NET_CTR_STAT_INC(NetIP_StatTxDatagramCtr);
*perr = NET_IP_ERR_NONE;
break;
case NET_ERR_RX:
case NET_ERR_TX:
NET_CTR_ERR_INC(NetIP_ErrTxPktDiscardedCtr); /* See Note #3. */
*perr = NET_ERR_TX;
return; /* Prevent 'break NOT reachable' compiler warning. */
case NET_ERR_INIT_INCOMPLETE:
case NET_ERR_INVALID_PROTOCOL:
case NET_IP_ERR_INVALID_LEN_HDR:
case NET_IP_ERR_INVALID_FRAG:
case NET_IP_ERR_INVALID_OPT_TYPE:
case NET_IP_ERR_INVALID_OPT_LEN:
case NET_IP_ERR_TX_DEST_INVALID:
case NET_IP_ERR_INVALID_ADDR_HOST:
case NET_IP_ERR_INVALID_ADDR_NET:
case NET_IP_ERR_INVALID_ADDR_GATEWAY:
case NET_BUF_ERR_INVALID_IX:
case NET_BUF_ERR_INVALID_LEN:
case NET_UTIL_ERR_NULL_PTR:
case NET_UTIL_ERR_NULL_SIZE:
default:
NetIP_TxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_ReTx()
*
* Description : (1) Prepare & re-transmit packets from transport protocol layers to network interface layer :
*
* (a) Validate re-transmit packet
* (b) Prepare & re-transmit packet datagram
* (c) Update re-transmit statistics
*
*
* Argument(s) : pbuf Pointer to network buffer to re-transmit IP packet.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP datagram(s) successfully prepared & re-transmitted
* to network interface layer.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* -------- RETURNED BY NetIP_TxPktDiscard() : ---------
* NET_ERR_TX Transmit error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetTCP_TxConnReTxQ_Timeout().
*
* This function is an INTERNAL network protocol suite function & SHOULD NOT be called by
* application function(s).
*
* Note(s) : (2) NetIP_ReTx() blocked until network initialization completes.
*
* (3) Network buffer already freed by lower layer; only increment error counter.
*********************************************************************************************************
*/
/*$PAGE*/
void NetIP_ReTx (NET_BUF *pbuf,
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;
#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) {
NetIP_TxPktDiscard(pbuf, perr);
NET_CTR_ERR_INC(NetIP_ErrNullPtrCtr);
return;
}
#endif
/* -------------- VALIDATE RE-TX IP PKT --------------- */
pbuf_hdr = &pbuf->Hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (pbuf_hdr->IP_HdrIx == NET_BUF_IX_NONE) {
NetIP_TxPktDiscard(pbuf, perr);
NET_CTR_ERR_INC(NetIP_ErrTxInvalidBufIxCtr);
return;
}
#endif
/* ------------------- RE-TX IP PKT ------------------- */
NetIP_ReTxPkt(pbuf,
pbuf_hdr,
perr);
/* ---------------- UPDATE RE-TX STATS ---------------- */
switch (*perr) {
case NET_IP_ERR_NONE:
case NET_IF_ERR_NONE:
NET_CTR_STAT_INC(NetIP_StatTxDatagramCtr);
*perr = NET_IP_ERR_NONE;
break;
case NET_ERR_RX:
case NET_ERR_TX:
NET_CTR_ERR_INC(NetIP_ErrTxPktDiscardedCtr); /* See Note #3. */
*perr = NET_ERR_TX;
return; /* Prevent 'break NOT reachable' compiler warning. */
case NET_ERR_INIT_INCOMPLETE:
case NET_IP_ERR_TX_DEST_INVALID:
case NET_IP_ERR_INVALID_ADDR_HOST:
case NET_IP_ERR_INVALID_ADDR_NET:
case NET_IP_ERR_INVALID_ADDR_GATEWAY:
case NET_UTIL_ERR_NULL_PTR:
case NET_UTIL_ERR_NULL_SIZE:
default:
NetIP_TxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
*********************************************************************************************************
* LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* NetIP_RxPktValidateBuf()
*
* Description : Validate received buffer header as IP protocol.
*
* Argument(s) : pbuf_hdr Pointer to network buffer header that received IP packet.
* -------- Argument validated in NetIP_Rx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Received buffer's IP header validated.
* NET_ERR_INVALID_PROTOCOL Buffer's protocol type is NOT IP.
* NET_BUF_ERR_INVALID_IX Invalid buffer index.
*
* Return(s) : none.
*
* Caller(s) : NetIP_Rx().
*
* Note(s) : none.
*********************************************************************************************************
*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetIP_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 IP BUF HDR --------------- */
if (pbuf_hdr->ProtocolHdrType != NET_PROTOCOL_TYPE_IP) {
NET_CTR_ERR_INC(Net_ErrInvalidProtocolCtr);
*perr = NET_ERR_INVALID_PROTOCOL;
return;
}
if (pbuf_hdr->IP_HdrIx == NET_BUF_IX_NONE) {
NET_CTR_ERR_INC(NetIP_ErrRxInvalidBufIxCtr);
*perr = NET_BUF_ERR_INVALID_IX;
return;
}
*perr = NET_IP_ERR_NONE;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktValidate()
*
* Description : (1) Validate received IP packet :
*
* (a) (1) Validate the received packet's following IP header fields :
*
* (A) Version
* (B) Header Length
* (C) Total Length See Note #4
* (D) Flags
* (E) Fragment Offset
* (F) Protocol
* (G) Check-Sum See Note #5
* (H) Source Address See Note #9c
* (I) Destination Address See Note #9d
* (J) Options
*
* (2) Validation ignores the following IP header fields :
*
* (A) Type of Service (TOS)
* (B) Identification (ID)
* (C) Time-to-Live (TTL)
*
* (b) Convert the following IP header fields from network-order to host-order :
*
* (1) Total Length See Notes #1bB1 & #3b
* (2) Identification (ID) See Note #1bB2
* (3) Flags/Fragment Offset See Note #1bB3
* (4) Check-Sum See Note #5d
* (5) Source Address See Notes #1bB4 & #3c
* (6) Destination Address See Notes #1bB5 & #3d
* (7) All Options' multi-octet words See Notes #1bB6 & #1bC
*
* (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.
*
* (B) The following IP header fields are converted & stored in network buffer
* variables :
*
* (1) Total Length
* (2) Identification (ID)
* (3) Flags/Fragment Offset
* (4) Source Address
* (5) Destination Address
* (6) IP Options' multi-octet words
*
* (C) Since any IP packet may receive a number of various IP options that may
* require conversion from network-order to host-order, IP options are copied
* into a separate network buffer for validation, conversion, & demultiplexing.
*
* (c) Update network buffer's protocol controls.
*
* (d) Process IP packet in ICMP Receive Handler.
*
*$PAGE*
* Argument(s) : pbuf Pointer to network buffer that received IP packet.
* ---- Argument checked in NetIP_Rx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Rx().
*
* pip_hdr Pointer to received packet's IP header.
* ------- Argument validated in NetIP_Rx()/NetIP_RxPktValidateBuf().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Received packet validated.
* NET_IP_ERR_INVALID_VER Invalid IP version.
* NET_IP_ERR_INVALID_LEN_HDR Invalid IP header length.
* NET_IP_ERR_INVALID_LEN_TOT Invalid IP total length.
* NET_IP_ERR_INVALID_LEN_DATA Invalid IP data length.
* NET_IP_ERR_INVALID_FLAG Invalid IP flags.
* NET_IP_ERR_INVALID_FRAG Invalid IP fragmentation.
* NET_IP_ERR_INVALID_PROTOCOL Invalid/unknown protocol type.
* NET_IP_ERR_INVALID_CHK_SUM Invalid IP check-sum.
* NET_IP_ERR_INVALID_ADDR_SRC Invalid IP source address.
* NET_IP_ERR_INVALID_ADDR_DEST Invalid IP destination address.
* NET_IP_ERR_INVALID_ADDR_BROADCAST Invalid IP broadcast.
*
* - RETURNED BY NetIP_RxPktValidateOpt() : --
* NET_IP_ERR_RX_OPT_BUF_NONE_AVAIL No available buffers to process IP options.
* NET_IP_ERR_RX_OPT_BUF_WR IP options failed to write to buffer.
* NET_IP_ERR_INVALID_OPT Invalid IP option.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP option length.
* NET_IP_ERR_INVALID_OPT_NBR Invalid IP option number of same option.
* NET_IP_ERR_INVALID_OPT_END Invalid IP option list ending.
* NET_IP_ERR_INVALID_OPT_FLAG Invalid IP option flag.
*
* Return(s) : none.
*
* Caller(s) : NetIP_Rx().
*
* Note(s) : (2) See 'net_ip.h IP HEADER' for IP header format.
*
* (3) 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_icmp.c NetICMP_TxMsgErr() Note #3') :
*
* (a) Header Length
* (b) Total Length
* (c) Source Address
* (d) Destination Address
*
* (4) (a) In addition to validating that the IP header Total Length is greater than or equal to the
* IP header Header Length, the IP total length is compared to the remaining packet length
* which should be identical.
*
* (b) (1) However, some network interface frame types append 'pad' octets (octets with a dummy
* value to be ignored) if the data length for the frame does NOT meet the frame's
* required minimum size. Thus, if the IP total length is NOT greater than the frame's
* minimum size, then pad octets were appended & the IP total length CANNOT be compared.
*
* (2) If pad octets were appended to the total frame length, then the current data length
* may be greater than the IP datagram length. However, this value should be reset to
* the IP datagram's length to correctly calculate higher-layer application data length.
*
* (5) (a) IP header Check-Sum field MUST be validated BEFORE (or AFTER) 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 IP header Check-Sum CANNOT be validated AFTER SOME but NOT ALL
* multi-octet words have been converted from network-order to host-order.
*
* (b) However, ALL received packets' multi-octet words are converted in local or network
* buffer variables ONLY (see Note #1bA). Therefore, IP header Check-Sum may be validated
* at any point.
*
* (c) For convenience, the IP header Check-Sum is validated AFTER IP Version, Header Length,
* & Total Length fields have been validated. Thus, invalid IP version or length packets
* are quickly discarded (see Notes #9a, #8a, & #8b) & the total IP header length
* (in octets) will already be calculated for the IP Check-Sum calculation.
*
* (d) After the IP header 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.
*$PAGE*
* (6) (a) RFC #791, Section 3.2 'Fragmentation and Reassembly' states that "if an internet datagram
* is fragmented" :
*
* (1) "Fragments are counted in units of 8 octets."
* (2) "The minimum fragment is 8 octets."
*
* (b) (1) However, this CANNOT apply "if this is the last fragment" ...
* (A) "(that is the more fragments field is zero)"; ...
* (2) Which may be of ANY size.
*
* See also 'net_ip.h IP FRAGMENTATION DEFINES Note #1a'.
*
* (7) (a) RFC #792, Section 'Destination Unreachable Message : Description' states that "if, in
* the destination host, the IP module cannot deliver the datagram because the indicated
* protocol module ... is not active, the destination host may send a destination unreachable
* message to the source host".
*
* (b) Default case already invalidated earlier in this function. However, the default case
* is included as an extra precaution in case 'Protocol' is incorrectly modified.
*
* (8) ICMP Error Messages are sent if any of the following IP header fields are invalid :
*
* (a) Header Length ICMP 'Parameter Problem' Error Message
* (b) Total Length ICMP 'Parameter Problem' Error Message
* (c) Flags ICMP 'Parameter Problem' Error Message
* (d) Fragment Offset ICMP 'Parameter Problem' Error Message
* (e) Protocol ICMP 'Unreachable Protocol' Error Message
* (f) Options ICMP 'Parameter Problem' Error Messages
* [see NetIP_RxPktValidateOpt()]
*
* (9) RFC #1122, Section 3.2.1 requires that IP packets with the following invalid IP header
* fields be "silently discarded" :
*
* (a) Version RFC #1122, Section 3.2.1.1
* (b) Check-Sum RFC #1122, Section 3.2.1.2
*
* (c) Source Address
* (1) MUST NOT be one of the following :
* (A) Limited Broadcast RFC #1122, Section 3.2.1.3.(c)
* (B) Directed Broadcast RFC #1122, Section 3.2.1.3.(d)
* (C) Subnet Broadcast RFC #1122, Section 3.2.1.3.(e)
* (D) Multicast RFC #1122, Section 3.2.1.3
* (2) SHOULD NOT be one of the following :
* (A) Localhost RFC #1122, Section 3.2.1.3.(g)
*
* (d) Destination Address
* (1) MUST be one of the following :
* (A) This host's RFC #1122, Section 3.2.1.3
* (B) Localhost RFC #1122, Section 3.2.1.3.(g)
* (C) Limited Broadcast RFC #1122, Section 3.2.1.3.(c)
* (D) Directed Broadcast RFC #1122, Section 3.2.1.3.(d)
* (E) Subnet Broadcast RFC #1122, Section 3.2.1.3.(e)
* (2) MUST NOT be one of the following :
* (A) This Host RFC #1122, Section 3.2.1.3.(a)
* (B) Specified Host RFC #1122, Section 3.2.1.3.(b)
*
* (3) (A) RFC #1122, Section 3.3.6 states that "when a host sends a datagram
* to a link-layer broadcast address, the IP destination address MUST
* be a legal IP broadcast or IP multicast address".
*
* Thus, any packet received as an IP broadcast destination address
* MUST also have been received as a link-layer broadcast.
*
* (B) RFC #1122, Section 3.3.6 further states that "a host SHOULD silently
* discard a datagram that is received via a link-layer broadcast ...
* but does not specify an IP multicast or broadcast destination address".
*
* Thus, any packet received as a link-layer broadcast MUST also be
* received as an IP broadcast.
*
* (C) Therefore, any packet received as EITHER a link-layer broadcast or
* an IP broadcast, but not BOTH, MUST be silently discarded.
*
* (10) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_RxPktValidate (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_HDR *pip_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
NET_ERR msg_err;
CPU_INT08U ip_ver;
CPU_INT08U ip_hdr_len;
CPU_INT16U ip_hdr_len_tot;
CPU_INT16U ip_flags;
CPU_INT16U ip_frag_offset;
CPU_INT16U protocol_ix;
CPU_BOOLEAN ip_flag_reserved;
CPU_BOOLEAN ip_flag_dont_frag;
CPU_BOOLEAN ip_flag_frags_more;
CPU_BOOLEAN ip_chk_sum_valid;
CPU_BOOLEAN ip_broadcast;
CPU_BOOLEAN rx_broadcast;
/* ---------------- CONVERT IP FIELDS ----------------- */
/* See Note #3. */
NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->IP_TotLen, &pip_hdr->TotLen);
NET_UTIL_VAL_COPY_GET_NET_32(&pbuf_hdr->IP_AddrSrc, &pip_hdr->AddrSrc);
NET_UTIL_VAL_COPY_GET_NET_32(&pbuf_hdr->IP_AddrDest, &pip_hdr->AddrDest);
/* ----------------- VALIDATE IP VER ------------------ */
ip_ver = pip_hdr->Ver_HdrLen & NET_IP_HDR_VER_MASK; /* See 'net_ip.h IP HEADER Note #2'. */
ip_ver >>= NET_IP_HDR_VER_SHIFT;
if (ip_ver != NET_IP_HDR_VER) { /* Validate IP ver. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrVerCtr);
*perr = NET_IP_ERR_INVALID_VER;
return;
}
/* --------------- VALIDATE IP HDR LEN ---------------- */
/* See 'net_ip.h IP HEADER Note #2'. */
ip_hdr_len = pip_hdr->Ver_HdrLen & NET_IP_HDR_LEN_MASK;
ip_hdr_len_tot = (CPU_INT16U)ip_hdr_len * NET_IP_HDR_LEN_WORD_SIZE;
pbuf_hdr->IP_HdrLen = (CPU_INT16U)ip_hdr_len_tot; /* See Note #3a. */
if (ip_hdr_len < NET_IP_HDR_LEN_MIN) { /* If hdr len < min hdr len, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrLenCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_HDR_LEN, &msg_err);
*perr = NET_IP_ERR_INVALID_LEN_HDR;
return;
}
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (ip_hdr_len > NET_IP_HDR_LEN_MAX) { /* If hdr len > max hdr len, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrLenCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_HDR_LEN, &msg_err);
*perr = NET_IP_ERR_INVALID_LEN_HDR;
return;
}
#endif
/* --------------- VALIDATE IP TOT LEN ---------------- */
#if 0 /* See Note #3b. */
NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->IP_TotLen, &pip_hdr->TotLen);
#endif
if (pbuf_hdr->IP_TotLen < ip_hdr_len_tot) { /* If IP tot len < hdr len, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrTotLenCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_TOT_LEN, &msg_err);
*perr = NET_IP_ERR_INVALID_LEN_TOT;
return;
}
if (pbuf_hdr->IP_TotLen >= pbuf_hdr->IF_DataLenMin) { /* If IP tot len >= min net IF data size & ... */
if (pbuf_hdr->IP_TotLen != pbuf_hdr->DataLen) { /* .. IP tot len != rem pkt len, rtn err (see Note #4). */
NET_CTR_ERR_INC(NetIP_ErrRxHdrTotLenCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_TOT_LEN, &msg_err);
*perr = NET_IP_ERR_INVALID_LEN_TOT;
return;
}
} else { /* Else reset data len to IP tot len (see Note #4b2). */
pbuf_hdr->DataLen = (NET_BUF_SIZE)pbuf_hdr->IP_TotLen;
}
pbuf_hdr->IP_DataLen = pbuf_hdr->IP_TotLen - pbuf_hdr->IP_HdrLen;
/*$PAGE*/
/* ---------------- VALIDATE IP CHK SUM --------------- */
/* See Note #5. */
ip_chk_sum_valid = NetUtil_16BitOnesCplChkSumHdrVerify((void *)pip_hdr,
(CPU_INT16U)ip_hdr_len_tot,
(NET_ERR *)perr);
if (ip_chk_sum_valid != DEF_OK) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrChkSumCtr);
*perr = NET_IP_ERR_INVALID_CHK_SUM;
return;
}
#if 0 /* Conv to host-order NOT necessary (see Note #5d). */
(void)NET_UTIL_VAL_GET_NET_16(&pip_hdr->ChkSum);
#endif
/* ------------------ CONVERT IP ID ------------------- */
NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->IP_ID, &pip_hdr->ID);
/* ---------------- VALIDATE IP FLAGS ----------------- */
/* See 'net_ip.h IP HEADER Note #4'. */
NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->IP_Flags_FragOffset, &pip_hdr->Flags_FragOffset);
ip_flags = pbuf_hdr->IP_Flags_FragOffset & NET_IP_HDR_FLAG_MASK;
#if 1 /* ???? Allow invalid reserved flag for rx'd datagrams? */
ip_flag_reserved = DEF_BIT_IS_SET_ANY(ip_flags, NET_IP_HDR_FLAG_RESERVED);
if (ip_flag_reserved != DEF_NO) { /* If reserved flag bit set, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrFlagsCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_FLAGS, &msg_err);
*perr = NET_IP_ERR_INVALID_FLAG;
return;
}
#endif
/* ----------------- VALIDATE IP FRAG ----------------- */
/* See 'net_ip.h IP HEADER Note #4'. */
ip_flag_dont_frag = DEF_BIT_IS_SET(ip_flags, NET_IP_HDR_FLAG_FRAG_DONT);
ip_flag_frags_more = DEF_BIT_IS_SET(ip_flags, NET_IP_HDR_FLAG_FRAG_MORE);
if (ip_flag_dont_frag != DEF_NO) { /* If 'Don't Frag' flag set & ... */
if (ip_flag_frags_more != DEF_NO) { /* ... 'More Frags' flag set, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrFragCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_FRAG_OFFSET, &msg_err);
*perr = NET_IP_ERR_INVALID_FRAG;
return;
}
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, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrFragCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_FRAG_OFFSET, &msg_err);
*perr = NET_IP_ERR_INVALID_FRAG;
return;
}
}
if (ip_flag_frags_more != DEF_NO) { /* If 'More Frags' set (see Note #6b1A) ... */
/* ... & IP data len NOT multiple of ... */
if ((pbuf_hdr->IP_DataLen % NET_IP_FRAG_SIZE_UNIT) != 0) { /* ... frag size units (see Note #6a), rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrFragCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_TOT_LEN, &msg_err);
*perr = NET_IP_ERR_INVALID_FRAG;
return;
}
}
/* --------------- VALIDATE IP PROTOCOL --------------- */
switch (pip_hdr->Protocol) { /* See 'net_ip.h IP HEADER Note #5'. */
case NET_IP_HDR_PROTOCOL_ICMP:
case NET_IP_HDR_PROTOCOL_TCP:
case NET_IP_HDR_PROTOCOL_UDP:
break;
default: /* See Note #7a. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrProtocolCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_DEST_UNREACH, NET_ICMP_MSG_CODE_DEST_PROTOCOL, NET_ICMP_MSG_PTR_NONE, &msg_err);
*perr = NET_IP_ERR_INVALID_PROTOCOL;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/*$PAGE*/
/* ------------- VALIDATE IP SRC ADDR ------------- */
/* See Note #9c. */
#if 0 /* See Note #3c. */
NET_UTIL_VAL_COPY_GET_NET_32(&pbuf_hdr->IP_AddrSrc, &pip_hdr->AddrSrc);
#endif
/* Chk invalid localhost (see Note #9c2A). */
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_LOCAL_HOST_MASK) == NET_IP_ADDR_LOCAL_HOST) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
/* Chk invalid limited broadcast (see Note #9c1A). */
if (pbuf_hdr->IP_AddrSrc == NET_IP_ADDR_BROADCAST) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
/* Chk invalid Class-A broadcast (see Note #9c1B). */
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_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 broadcast (see Note #9c1B). */
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_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 broadcast (see Note #9c1B). */
if ((pbuf_hdr->IP_AddrSrc & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
} else { /* Discard invalid addr class (see Note #10). */
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
/* Chk invalid subnet broadcast (see Note #9c1C). */
if (NetIP_AddrThisHostSubnetMask != NET_IP_ADDR_NONE) {
if ((pbuf_hdr->IP_AddrSrc & NetIP_AddrThisHostSubnetMask) ==
NetIP_AddrThisHostSubnetNet ) {
if ((pbuf_hdr->IP_AddrSrc & NetIP_AddrThisHostSubnetMaskHost) ==
(NET_IP_ADDR_BROADCAST & NetIP_AddrThisHostSubnetMaskHost)) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
}
}
/*$PAGE*/
/* ------------- VALIDATE IP DEST ADDR ------------ */
/* See Note #9d. */
#if 0 /* See Note #3d. */
NET_UTIL_VAL_COPY_GET_NET_32(&pbuf_hdr->IP_AddrDest, &pip_hdr->AddrDest);
#endif
ip_broadcast = DEF_NO;
if (pbuf_hdr->IP_AddrDest == NetIP_AddrThisHost) { /* Chk this host's addr (see Note #9d1A). */
if (NetIP_AddrThisHost == NET_IP_ADDR_NONE) { /* Chk invalid 'This Host' (see Note #9d2A). */
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
} else {
/* Chk localhost (see Note #9d1B). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_LOCAL_HOST_MASK) == NET_IP_ADDR_LOCAL_HOST) {
/* Chk localhost invalid addrs. */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_LOCAL_HOST_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_LOCAL_HOST_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_LOCAL_HOST_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_LOCAL_HOST_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
NET_CTR_STAT_INC(NetIP_StatRxDestLocalCtr);
} else {
/* Chk invalid 'This Host' (see Note #9d2A). */
if (pbuf_hdr->IP_AddrDest == NET_IP_ADDR_THIS_HOST) {
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/*$PAGE*/
/* Chk limited broadcast (see Note #9d1C). */
if (pbuf_hdr->IP_AddrDest != NET_IP_ADDR_BROADCAST) {
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
/* Chk Class-A specified host (see Note #9d2B). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/* Chk Class-A broadcast (see Note #9d1D). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
ip_broadcast = DEF_YES;
}
} else if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
/* Chk Class-B specified host (see Note #9d2B). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/* Chk Class-B broadcast (see Note #9d1D). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
ip_broadcast = DEF_YES;
}
} else if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
/* Chk Class-C specified host (see Note #9d2B). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/* Chk Class-C broadcast (see Note #9d1D). */
if ((pbuf_hdr->IP_AddrDest & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
ip_broadcast = DEF_YES;
}
} else { /* Discard invalid addr class (see Note #10). */
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/* Chk subnet broadcast (see Note #9d1E). */
if ((pbuf_hdr->IP_AddrDest & NetIP_AddrThisHostSubnetMask) ==
NetIP_AddrThisHostSubnetNet ) {
if ((pbuf_hdr->IP_AddrDest & NetIP_AddrThisHostSubnetMaskHost) ==
(NET_IP_ADDR_BROADCAST & NetIP_AddrThisHostSubnetMaskHost)) {
ip_broadcast = DEF_YES;
}
}
} else {
ip_broadcast = DEF_YES;
}
/* If NOT this host's or localhost addr, ... */
if (ip_broadcast != DEF_YES) { /* ... & NOT broadcast addr; ... */
NET_CTR_ERR_INC(NetIP_ErrRxDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST; /* ... rtn err. */
return;
}
}
}
/* Chk invalid broadcast (see Note #9d3). */
rx_broadcast = DEF_BIT_IS_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_RX);
if (ip_broadcast == DEF_NO) { /* If IP broadcast rx'd ... */
if (rx_broadcast != DEF_NO) { /* ... NOT also net IF broadcast rx'd, ... */
NET_CTR_ERR_INC(NetIP_ErrRxDestBroadcastCtr);
*perr = NET_IP_ERR_INVALID_ADDR_BROADCAST; /* ... rtn err. */
return;
}
} else { /* If NO IP broadcast rx'd ... */
if (rx_broadcast != DEF_YES) { /* ... BUT net IF broadcast rx'd, ... */
NET_CTR_ERR_INC(NetIP_ErrRxDestBroadcastCtr);
*perr = NET_IP_ERR_INVALID_ADDR_BROADCAST; /* ... rtn err. */
return;
}
NET_CTR_STAT_INC(NetIP_StatRxDestBroadcastCtr);
}
/*$PAGE*/
/* ----------------- VALIDATE IP OPTS ----------------- */
if (ip_hdr_len_tot > NET_IP_HDR_SIZE_MIN) { /* If hdr len > min, validate/process IP opts. */
NetIP_RxPktValidateOpt((NET_BUF *)pbuf,
(NET_BUF_HDR *)pbuf_hdr,
(NET_IP_HDR *)pip_hdr,
(CPU_INT08U )ip_hdr_len_tot,
(NET_ERR *)perr);
if (*perr != NET_IP_ERR_NONE) {
return;
}
}
/* ----------------- UPDATE BUF CTRLS ----------------- */
#if 0 /* See Note #3a. */
pbuf_hdr->IP_HdrLen = ip_hdr_len_tot;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (pbuf_hdr->IP_HdrLen > pbuf_hdr->DataLen) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrDataLenCtr);
*perr = NET_IP_ERR_INVALID_LEN_DATA;
return;
}
#endif
pbuf_hdr->DataLen -= (NET_BUF_SIZE) pbuf_hdr->IP_HdrLen;
protocol_ix = (CPU_INT16U )(pbuf_hdr->IP_HdrIx + pbuf_hdr->IP_HdrLen);
switch (pip_hdr->Protocol) {
case NET_IP_HDR_PROTOCOL_ICMP:
pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_ICMP;
pbuf_hdr->ICMP_MsgIx = protocol_ix;
break;
case NET_IP_HDR_PROTOCOL_TCP:
pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_TCP;
pbuf_hdr->TCP_UDP_HdrDataIx = protocol_ix;
break;
case NET_IP_HDR_PROTOCOL_UDP:
pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_UDP;
pbuf_hdr->TCP_UDP_HdrDataIx = protocol_ix;
break;
default: /* See Note #7b. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrProtocolCtr);
*perr = NET_IP_ERR_INVALID_PROTOCOL;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ------------------ ICMP RX HANDLER ----------------- */
NetICMP_HandlerRx(pbuf);
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktValidateOpt()
*
* Description : (1) Validate & process received packet's IP options :
*
* (a) Get buffer to process IP options See 'NetIP_RxPktValidate() Note #1bC'
* (b) Decode/validate IP options
*
*
* Argument(s) : pbuf Pointer to network buffer that received IP packet.
* ---- Argument checked in NetIP_Rx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Rx().
*
* pip_hdr Pointer to received packet's IP header.
* ------- Argument validated in NetIP_Rx()/NetIP_RxPktValidateBuf().
*
* ip_hdr_len_size Length of received packet's IP header.
* --------------- Argument validated in NetIP_RxPktValidate().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP options validated & processed.
* NET_IP_ERR_RX_OPT_BUF_NONE_AVAIL No available buffers to process IP options.
* NET_IP_ERR_RX_OPT_BUF_WR IP options failed to write to buffer.
* NET_IP_ERR_INVALID_OPT Invalid IP option.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP option length.
* NET_IP_ERR_INVALID_OPT_NBR Invalid IP option number of same option.
* NET_IP_ERR_INVALID_OPT_END Invalid IP option list ending.
* NET_IP_ERR_INVALID_OPT_FLAG Invalid IP option flag.
*
* Return(s) : none.
*
* Caller(s) : NetIP_RxPktValidate().
*
* Note(s) : (2) (a) See 'net_ip.h IP HEADER OPTIONS DEFINES' for supported IP options' summary.
*
* (b) See 'net_ip.c Note #5' for unsupported IP options.
*
* (3) RFC #1122, Section 3.2.1.8 lists the processing of the following IP options as optional :
*
* (a) Record Route RFC #1122, Section 3.2.1.8.(d)
* (b) Internet Timestamp RFC #1122, Section 3.2.1.8.(e)
*
* (4) Each option's length MUST be multiples of NET_IP_HDR_OPT_SIZE_WORD octets so that "the
* beginning of a subsequent option [aligns] on a 32-bit boundary" (RFC #791, Section 3.1
* 'Options : No Operation').
*
* (5) RFC #1122, Section 3.2.1.8.(c) prohibits "an IP header" from transmitting with "more
* than one Source Route option".
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_RxPktValidateOpt (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_HDR *pip_hdr,
CPU_INT08U ip_hdr_len_size,
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_ERR err;
NET_BUF *popt_buf;
NET_BUF_HDR *popt_buf_hdr;
CPU_INT08U *popts;
CPU_INT08U opt_list_len_size;
CPU_INT08U opt_list_len_rem;
CPU_INT08U opt_len;
CPU_INT08U opt_nbr_src_routes;
CPU_INT08U opt_ix_err;
CPU_INT16U opt_ix;
CPU_BOOLEAN opt_err;
CPU_BOOLEAN opt_list_end;
opt_list_len_size = ip_hdr_len_size - NET_IP_HDR_SIZE_MIN; /* Calc opt list len size. */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ----------- VALIDATE IP HDR OPT LIST SIZE ---------- */
if (opt_list_len_size > NET_IP_HDR_OPT_SIZE_MAX) { /* If tot opt len > max opt size, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrOptsCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_OPTS, &err);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return;
}
if ((opt_list_len_size % NET_IP_HDR_OPT_SIZE_WORD) != 0) { /* If tot opt len NOT multiple of opt size, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrRxHdrOptsCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, NET_ICMP_PTR_IX_IP_HDR_OPTS, &err);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return;
}
#endif
/* ------------ GET BUF TO PROCESS IP OPTS ------------ */
opt_ix = NET_IP_OPT_IX_RX;
popt_buf = NetBuf_Get((NET_BUF_SIZE) opt_list_len_size,
(NET_BUF_SIZE) opt_ix,
(CPU_INT16U ) NET_BUF_FLAG_NONE,
(NET_ERR *)&err);
if (err != NET_BUF_ERR_NONE) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrOptsBufNoneAvailCtr);
*perr = NET_IP_ERR_RX_OPT_BUF_NONE_AVAIL;
return;
}
NetBuf_DataWr((NET_BUF *) popt_buf, /* Copy IP opts from rx'd pkt to IP opt buf. */
(NET_BUF_SIZE) opt_ix,
(NET_BUF_SIZE) opt_list_len_size,
(CPU_INT08U *)&pip_hdr->Opts[0],
(NET_ERR *)&err);
if (err != NET_BUF_ERR_NONE) {
NET_CTR_ERR_INC(NetIP_ErrRxHdrOptsBufWrCtr);
*perr = NET_IP_ERR_RX_OPT_BUF_WR;
return;
}
/* Init IP opt buf ctrls. */
pbuf_hdr->IP_OptPtr = (void *) popt_buf;
popt_buf_hdr = (NET_BUF_HDR *)&popt_buf->Hdr;
popt_buf_hdr->IP_HdrIx = (CPU_INT16U ) opt_ix;
popt_buf_hdr->IP_HdrLen = (CPU_INT16U ) opt_list_len_size;
popt_buf_hdr->TotLen = (NET_BUF_SIZE ) popt_buf_hdr->IP_HdrLen;
popt_buf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_IP_OPT;
/*$PAGE*/
opt_err = DEF_NO;
opt_list_end = DEF_NO;
opt_nbr_src_routes = 0;
popts = (CPU_INT08U *)&popt_buf->Data[opt_ix];
opt_list_len_rem = opt_list_len_size;
/* ------------- DECODE/VALIDATE IP OPTS -------------- */
while (opt_list_len_rem > 0) { /* Process each opt in list (see Notes #2 & #4). */
switch (*popts) {
case NET_IP_HDR_OPT_END_LIST: /* ------------------- END OPT LIST ------------------- */
opt_list_end = DEF_YES; /* Mark end of opt list. */
opt_len = NET_IP_HDR_OPT_SIZE_WORD;
break;
case NET_IP_HDR_OPT_NOP: /* --------------------- NOP OPT ---------------------- */
opt_len = NET_IP_HDR_OPT_SIZE_WORD;
break;
case NET_IP_HDR_OPT_ROUTE_SRC_LOOSE: /* ---------------- SRC/REC ROUTE OPTS ---------------- */
case NET_IP_HDR_OPT_ROUTE_SRC_STRICT:
case NET_IP_HDR_OPT_ROUTE_REC:
if (opt_list_end == DEF_NO) {
if (opt_nbr_src_routes < 1) {
opt_nbr_src_routes++;
opt_err = NetIP_RxPktValidateOptRoute(popts, opt_list_len_rem, &opt_len, perr);
} else { /* If > 1 src route opt, rtn err (see Note #5). */
*perr = NET_IP_ERR_INVALID_OPT_NBR;
opt_err = DEF_YES;
}
} else { /* If opt found AFTER end of opt list, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_END;
opt_err = DEF_YES;
}
break;
case NET_IP_HDR_OPT_TS: /* --------------------- TS OPTS ---------------------- */
if (opt_list_end == DEF_NO) {
opt_err = NetIP_RxPktValidateOptTS(popts, opt_list_len_rem, &opt_len, perr);
} else { /* If opt found AFTER end of opt list, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_END;
opt_err = DEF_YES;
}
break;
#if 0 /* ----------------- UNSUPPORTED OPTS ----------------- */
/* See Note #2b. */
case NET_IP_HDR_OPT_SECURITY:
case NET_IP_HDR_OPT_SECURITY_EXTENDED:
/* 'break' intentionally omitted; do NOT move from the */
/* ... following case : 'default'. */
#endif
default: /* ------------------- INVALID OPTS ------------------- */
*perr = NET_IP_ERR_INVALID_OPT;
opt_err = DEF_YES;
break;
}
if (opt_err == DEF_NO) {
if (opt_list_len_rem >= opt_len) {
opt_list_len_rem -= opt_len;
popts += opt_len;
} else { /* If rem opt list len NOT multiple of opt size, ... */
*perr = NET_IP_ERR_INVALID_OPT_LEN; /* ... rtn err. */
opt_err = DEF_YES;
}
}
if (opt_err != DEF_NO) { /* If ANY opt errs, tx ICMP err msg. */
opt_ix_err = NET_ICMP_PTR_IX_IP_HDR_OPTS + (opt_list_len_size - opt_list_len_rem);
NET_CTR_ERR_INC(NetIP_ErrRxHdrOptsCtr);
NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_PARAM_PROB, NET_ICMP_MSG_CODE_PARAM_PROB_IP_HDR, opt_ix_err, &err);
return;
}
}
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktValidateOptRoute()
*
* Description : (1) Validate & process Source Route options :
*
* (a) Convert ALL Source Route IP addresses from network-order to host-order
* (b) Add this host's IP address to Source Route
*
* (2) See 'net_ip.h IP SOURCE ROUTE OPTION DATA TYPE' for Source Route options summary.
*
*
* Argument(s) : popts Pointer to Source Route option.
* ----- Argument validated in NetIP_RxPktValidateOpt().
*
* opt_list_len_rem Remaining option list length (in octets).
*
* popt_len Pointer to variable that will receive the Source Route option length (in octets).
* -------- Argument validated in NetIP_RxPktValidateOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Source Route IP option validated & processed.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP option length.
*
* Return(s) : DEF_NO, NO Source Route option error.
*
* DEF_YES, otherwise.
*
* Caller(s) : NetIP_RxPktValidateOpt().
*
* Note(s) : (3) If Source Route option appends this host's IP address to the source route, the IP
* header check-sum is NOT re-calculated since the check-sum was previously validated
* in NetIP_RxPktValidate() & is NOT required for further validation or processing.
*
* (4) Default case already invalidated earlier in this function. However, the default
* case is included as an extra precaution in case any of the IP receive options is
* incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static CPU_BOOLEAN NetIP_RxPktValidateOptRoute (CPU_INT08U *popts,
CPU_INT08U opt_list_len_rem,
CPU_INT08U *popt_len,
NET_ERR *perr)
{
NET_IP_OPT_SRC_ROUTE *popt_route;
NET_IP_ADDR opt_addr;
CPU_INT08U opt_ptr;
CPU_INT08U opt_ix;
popt_route = (NET_IP_OPT_SRC_ROUTE *)popts;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ----------------- VALIDATE OPT TYPE ---------------- */
switch (popt_route->Type) {
case NET_IP_HDR_OPT_ROUTE_SRC_LOOSE:
case NET_IP_HDR_OPT_ROUTE_SRC_STRICT:
case NET_IP_HDR_OPT_ROUTE_REC:
break;
default:
*perr = NET_IP_ERR_INVALID_OPT;
return (DEF_YES); /* Prevent 'break NOT reachable' compiler warning. */
}
#endif
/* ----------------- VALIDATE OPT LEN ----------------- */
if (popt_route->Ptr > popt_route->Len) { /* If ptr exceeds opt len, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
if (popt_route->Len > opt_list_len_rem) { /* If opt len exceeds rem opt len, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
if ((popt_route->Len % NET_IP_HDR_OPT_SIZE_WORD) != 0) { /* If opt len NOT multiple of opt size, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
opt_ptr = NET_IP_OPT_ROUTE_PTR_ROUTE;
opt_ix = 0;
/* --------------- CONVERT TO HOST-ORDER -------------- */
while (opt_ptr < popt_route->Ptr) { /* Convert ALL src route addrs to host-order. */
popt_route->Route[opt_ix] = NET_UTIL_NET_TO_HOST_32(popt_route->Route[opt_ix]);
opt_ptr += NET_IP_HDR_OPT_SIZE_WORD;
opt_ix++;
}
/* ------------------- INSERT ROUTE ------------------- */
if (popt_route->Ptr < popt_route->Len) { /* If ptr < len, append this host addr to src route. */
switch (*popts) {
case NET_IP_HDR_OPT_ROUTE_SRC_LOOSE:
case NET_IP_HDR_OPT_ROUTE_REC:
opt_addr = NetIP_AddrThisHost;
NET_UTIL_VAL_COPY_GET_NET_32(&popt_route->Route[opt_ix], &opt_addr);
popt_route->Ptr += NET_IP_HDR_OPT_SIZE_WORD;
break;
case NET_IP_HDR_OPT_ROUTE_SRC_STRICT:
break;
default: /* See Note #4. */
*perr = NET_IP_ERR_INVALID_OPT;
return (DEF_YES); /* Prevent 'break NOT reachable' compiler warning. */
}
}
*popt_len = popt_route->Len; /* Rtn src route opt len. */
*perr = NET_IP_ERR_NONE;
return (DEF_NO);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktValidateOptTS()
*
* Description : (1) Validate & process Internet Timestamp options :
*
* (a) Convert ALL Internet Timestamps & Source Route IP addresses from network-order
* to host-order
* (b) Add current Internet Timestamp & this host's IP address to Internet Timestamp
*
* (2) See 'net_ip.h IP INTERNET TIMESTAMP OPTION DATA TYPE' for Internet Timestamp options summary.
*
*
* Argument(s) : popts Pointer to Internet Timestamp option.
* ----- Argument validated in NetIP_RxPktValidateOpt().
*
* opt_list_len_rem Remaining option list length (in octets).
*
* popt_len Pointer to variable that will return the Internet Timestamp option length
* -------- (in octets).
*
* Argument validated in NetIP_RxPktValidateOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Internet Timestamp IP option validated
* & processed.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP option length.
*
* Return(s) : DEF_NO, NO Internet Timestamp option error.
*
* DEF_YES, otherwise.
*
* Caller(s) : NetIP_RxPktValidateOpt().
*
* Note(s) : (3) If Internet Timestamp option appends the current Internet Timestamp &/or this host's
* IP address to the Internet Timestamp, the IP header check-sum is NOT re-calculated
* since the check-sum was previously validated in NetIP_RxPktValidate() & is NOT
* required for further validation or processing.
*********************************************************************************************************
*/
static CPU_BOOLEAN NetIP_RxPktValidateOptTS (CPU_INT08U *popts,
CPU_INT08U opt_list_len_rem,
CPU_INT08U *popt_len,
NET_ERR *perr)
{
NET_IP_OPT_TS *popt_ts;
NET_IP_OPT_TS_ROUTE *popt_ts_route;
NET_IP_ROUTE_TS *proute_ts;
CPU_INT08U opt_ptr;
CPU_INT08U opt_ix;
CPU_INT08U opt_ts_flags;
CPU_INT08U opt_ts_ovf;
NET_TS opt_ts;
NET_IP_ADDR opt_addr;
popt_ts = (NET_IP_OPT_TS *)popts;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ----------------- VALIDATE OPT TYPE ---------------- */
switch (popt_ts->Type) {
case NET_IP_HDR_OPT_TS:
break;
default:
*perr = NET_IP_ERR_INVALID_OPT;
return (DEF_YES); /* Prevent 'break NOT reachable' compiler warning. */
}
#endif
/* ----------------- VALIDATE OPT LEN ----------------- */
if (popt_ts->Ptr > popt_ts->Len) { /* If ptr exceeds opt len, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
if (popt_ts->Len > opt_list_len_rem) { /* If opt len exceeds rem opt len, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
/*$PAGE*/
opt_ptr = NET_IP_OPT_TS_PTR_TS;
opt_ix = 0;
opt_ts_flags = popt_ts->Ovf_Flags & NET_IP_OPT_TS_FLAG_MASK;
switch (opt_ts_flags) {
case NET_IP_OPT_TS_FLAG_TS_ONLY:
if ((popt_ts->Len % NET_IP_HDR_OPT_SIZE_WORD) != 0) { /* If opt len NOT multiple of opt size, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
/* --------------- CONVERT TO HOST-ORDER -------------- */
while (opt_ptr < popt_ts->Ptr) { /* Convert ALL TS's to host-order. */
popt_ts->TS[opt_ix] = NET_UTIL_NET_TO_HOST_32(popt_ts->TS[opt_ix]);
opt_ptr += NET_IP_HDR_OPT_SIZE_WORD;
opt_ix++;
}
/* --------------------- INSERT TS -------------------- */
if (popt_ts->Ptr < popt_ts->Len) { /* If ptr < len, append ts to list. */
opt_ts = NetUtil_TS_Get();
NET_UTIL_VAL_COPY_GET_NET_32(&popt_ts->TS[opt_ix], &opt_ts);
popt_ts->Ptr += NET_IP_HDR_OPT_SIZE_WORD;
} else { /* Else inc & chk ovf ctr. */
opt_ts_ovf = popt_ts->Ovf_Flags & NET_IP_OPT_TS_OVF_MASK;
opt_ts_ovf >>= NET_IP_OPT_TS_OVF_SHIFT;
opt_ts_ovf++;
if (opt_ts_ovf > NET_IP_OPT_TS_OVF_MAX) { /* If ovf ctr ovfs, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
}
break;
case NET_IP_OPT_TS_FLAG_TS_ROUTE_REC:
case NET_IP_OPT_TS_FLAG_TS_ROUTE_SPEC:
/* If opt len NOT multiple of opt size, rtn err. */
if ((popt_ts->Len % NET_IP_OPT_TS_ROUTE_SIZE) != NET_IP_HDR_OPT_SIZE_WORD) {
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
popt_ts_route = (NET_IP_OPT_TS_ROUTE *)popts;
proute_ts = &popt_ts_route->Route_TS[0];
/* --------------- CONVERT TO HOST-ORDER -------------- */
while (opt_ptr < popt_ts_route->Ptr) { /* Convert ALL src route addrs & ts's to host-order. */
proute_ts->Route[opt_ix] = NET_UTIL_NET_TO_HOST_32(proute_ts->Route[opt_ix]);
proute_ts->TS[opt_ix] = NET_UTIL_NET_TO_HOST_32(proute_ts->TS[opt_ix]);
opt_ptr += NET_IP_OPT_TS_ROUTE_SIZE;
opt_ix++;
}
/* ---------------- INSERT SRC ROUTE/TS --------------- */
if (popt_ts_route->Ptr < popt_ts_route->Len) { /* If ptr < len, append src route addr & ts to list. */
opt_addr = NetIP_AddrThisHost;
opt_ts = NetUtil_TS_Get();
NET_UTIL_VAL_COPY_GET_NET_32(&proute_ts->Route[opt_ix], &opt_addr);
NET_UTIL_VAL_COPY_GET_NET_32(&proute_ts->TS[opt_ix], &opt_ts);
popt_ts_route->Ptr += NET_IP_OPT_TS_ROUTE_SIZE;
} else { /* Else inc & chk ovf ctr. */
opt_ts_ovf = popt_ts->Ovf_Flags & NET_IP_OPT_TS_OVF_MASK;
opt_ts_ovf >>= NET_IP_OPT_TS_OVF_SHIFT;
opt_ts_ovf++;
if (opt_ts_ovf > NET_IP_OPT_TS_OVF_MAX) { /* If ovf ctr ovfs, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (DEF_YES);
}
}
break;
default: /* If invalid/unknown TS flag, rtn err. */
*perr = NET_IP_ERR_INVALID_OPT_FLAG;
return (DEF_YES); /* Prevent 'break NOT reachable' compiler warning. */
}
*popt_len = popt_ts->Len; /* Rtn TS opt len. */
*perr = NET_IP_ERR_NONE;
return (DEF_NO);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragReasm()
*
* Description : (1) Reassemble any IP datagram fragments :
*
* (a) Determine if received IP packet is a fragment
* (b) Reassemble IP fragments, when possible
*
* (2) (a) Received fragments are reassembled by sorting datagram fragments into fragment lists
* (also known as 'Fragmented Datagrams') grouped by the following IP header fields :
*
* (1) Source Address
* (2) Destination Address
* (3) Identification
* (4) Protocol
*
* See also Note #3a.
*
* (b) Fragment lists are linked to form a list of Fragment Lists. In the diagram below,
* network buffers in vertical columns represent fragments in the same fragment list/
* Fragmented Datagram. The head fragment of each fragment list/Fragmented Datagram
* is linked horizontally to form the list of Fragment Lists.
*
* (1) 'NetIP_FragReasmListsHead' points to the head of the Fragment Lists;
* 'NetIP_FragReasmListsTail' points to the tail of the Fragment Lists.
*
* (2) Fragment buffers' 'PrevPrimListPtr' & 'NextPrimListPtr' doubly-link each fragment
* list's head buffer to form the list of Fragment Lists.
*
* (3) Fragment buffer's 'PrevBufPtr' & 'NextBufPtr' doubly-link each fragment
* in a fragment list.
*
* (c) For each received fragment, all fragment lists are searched in order to insert the
* fragment into the appropriate fragment list--i.e. the fragment list with identical
* fragment list IP header field values (see Note #2a).
*
* (d) If a received fragment is the first fragment with its specific fragment list IP header
* field values, the received fragment starts a new fragment list which is added at the
* tail of the Fragment Lists.
*
* See also Note #3b2.
*
* (e) As fragments are received & processed into fragment lists, older fragment lists migrate
* to the head of the Fragment Lists. Once a fragment list is reassembled or discarded,
* it is removed from the Fragment Lists.
*
* (f) Fragment buffer size is irrelevant & ignored in the fragment reassembly procedure--
* i.e. the procedure functions correctly regardless of the buffer sizes used for any &
* all received fragments.
*
*
* | List of |
* |<----------- Fragmented Datagrams ------------>|
* | (see Note #2b) |
*
* Oldest Fragmented Datagram New fragment lists
* in Fragment Lists inserted at tail
* (see Note #2e) (see Note #2d)
*
* | NextPrimListPtr |
* | (see Note #2b2) |
* v | v
* |
* --- Head of ------- ------- v ------- ------- (see Note #2b1)
* ^ Fragment ---->| |------>| |------>| |------>| |
* | Lists | | | | | | | | Tail of
* | | |<------| |<------| |<------| |<---- Fragment
* | (see Note #2b1) | | | | ^ | | | | Lists
* | | | | | | | | | |
* | ------- ------- | ------- -------
* | | ^ | | ^
* | | | PrevPrimListPtr | |
* | v | (see Note #2b2) v |
* | ------- -------
* | | | |
* Fragments in the same | | | |
* Fragmented Datagram | | | |
* (see Note #2b) | | | |
* | | | | Fragments in a fragment
* | ------- ------- list may use different
* | | ^ | ^ size network buffers
* | NextBufPtr ---> | | <--- PrevBufPtr | | (see Note #2f)
* | (see Note #2b3) v | (see Note #2b3) v |
* | ------- ------- The last fragment in a
* | | | | | <--- fragment list may likely
* | | | | | use a smaller buffer size
* | | | -------
* | | |
* v | |
* --- -------
*
*
*$PAGE*
* Argument(s) : pbuf Pointer to network buffer that received IP packet.
* ---- Argument checked in NetIP_Rx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Rx().
*
* pip_hdr Pointer to received packet's IP header.
* ------- Argument checked in NetIP_RxPktValidate().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_RX_FRAG_NONE Datagram complete; NOT a fragment (see Note #3b1B).
*
* -------- RETURNED BY NetIP_RxPktFragListAdd() : ---------
* ------- RETURNED BY NetIP_RxPktFragListInsert() : -------
* NET_IP_ERR_RX_FRAG_REASM Fragments in reassembly progress.
* NET_IP_ERR_RX_FRAG_DISCARD Fragment &/or datagram discarded.
* NET_IP_ERR_RX_FRAG_OFFSET Invalid fragment offset.
* NET_IP_ERR_RX_FRAG_SIZE Invalid fragment size.
* NET_IP_ERR_RX_FRAG_LEN_TOT Invalid fragment datagram total IP length.
*
* ------- RETURNED BY NetIP_RxPktFragListInsert() : -------
* NET_IP_ERR_RX_FRAG_COMPLETE Datagram complete; fragments reassembled (see Note #3b3).
* NET_IP_ERR_RX_FRAG_SIZE_TOT Invalid fragmented datagram total size.
*
* Return(s) : Pointer to reassembled datagram, if fragment reassembly complete.
*
* Pointer to NULL, if fragment reassembly in progress.
*
* Pointer to fragment buffer, for any fragment discard error.
*
* Caller(s) : NetIP_Rx().
*
* Note(s) : (3) (a) RFC #791, Section 3.2 'Fragmentation & Reassembly' states that the following IP header
* fields are "used together ... to identify datagram fragments for reassembly" :
*
* (1) "Internet identification field (ID)", ...
* (2) "source" address, ...
* (3) "destination address", & ...
* (4) "protocol field".
*
* (b) RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly Procedure'
* states that :
*
* (1) (A) "If ... both [of the following IP header fields] ... are zero" ... :
* (1) "the fragment offset and" ...
* (2) "the more fragments"; ...
*
* (B) "Then ... this is a whole datagram ... and the datagram is forwarded to the
* next step in datagram processing."
*
* (2) "If no other fragment with [identical] buffer identifier[s] is [available] then
* [new] reassembly resources are allocated."
*
* See also 'NetIP_RxPktFragListAdd() Note #2'.
*
* (3) When a "fragment [finally] completes the datagram ... then the datagram is sent
* to the next step in datagram processing".
*
* (4) (a) Fragment lists are accessed by :
*
* (1) NetIP_RxPktFragReasm()
* (2) Fragment list's 'TMR->Obj' pointer during execution of NetIP_RxPktFragTimeout()
*
* (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 fragment lists since no asynchronous access from other network
* tasks is possible.
*********************************************************************************************************
*/
static NET_BUF *NetIP_RxPktFragReasm (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_HDR *pip_hdr,
NET_ERR *perr)
{
#if ((NET_CTR_CFG_STAT_EN == DEF_ENABLED) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_BOOLEAN frag;
CPU_BOOLEAN frag_done;
CPU_BOOLEAN ip_flag_frags_more;
CPU_INT16U ip_flags;
CPU_INT16U frag_offset;
CPU_INT16U frag_size;
NET_BUF *pfrag;
NET_BUF *pfrag_list;
NET_BUF_HDR *pfrag_list_buf_hdr;
NET_IP_HDR *pfrag_list_ip_hdr;
/*$PAGE*/
/* -------------- CHK FRAG REASM REQUIRED ------------- */
frag = DEF_NO;
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' set (see Note #3b1A2), ... */
frag = DEF_YES; /* ... mark as frag. */
}
frag_offset = pbuf_hdr->IP_Flags_FragOffset & NET_IP_HDR_FRAG_OFFSET_MASK;
if (frag_offset != NET_IP_HDR_FRAG_OFFSET_NONE) { /* If frag offset != 0 (see Note #3b1A1), ... */
frag = DEF_YES; /* ... mark as frag. */
}
if (frag != DEF_YES) { /* If pkt NOT a frag, ... */
*perr = NET_IP_ERR_RX_FRAG_NONE;
return (pbuf); /* ... rtn non-frag'd datagram (see Note #3b1B). */
}
NET_CTR_STAT_INC(NetIP_StatRxFragCtr);
/* ------------------- REASM FRAGS -------------------- */
frag_size = pbuf_hdr->IP_TotLen - pbuf_hdr->IP_HdrLen;
pfrag_list = NetIP_FragReasmListsHead;
frag_done = DEF_NO;
while (frag_done == DEF_NO) { /* Insert frag into a frag list. */
if (pfrag_list != (NET_BUF *)0) { /* Srch ALL existing frag lists first (see Note #2c). */
pfrag_list_buf_hdr = &pfrag_list->Hdr;
pfrag_list_ip_hdr = (NET_IP_HDR *)&pfrag_list->Data[pfrag_list_buf_hdr->IP_HdrIx];
/* If frag & this frag list's ... */
if (pbuf_hdr->IP_AddrSrc == pfrag_list_buf_hdr->IP_AddrSrc) { /* ... src addr (see Note #2a1) ... */
if (pbuf_hdr->IP_AddrDest == pfrag_list_buf_hdr->IP_AddrDest) { /* ... dest addr (see Note #2a2) ... */
if (pbuf_hdr->IP_ID == pfrag_list_buf_hdr->IP_ID) { /* ... ID (see Note #2a3) ... */
if (pip_hdr->Protocol == pfrag_list_ip_hdr->Protocol) { /* ... protocol (see Note #2a4) ... */
/* ... fields identical, ... */
pfrag = NetIP_RxPktFragListInsert(pbuf, /* ... insert frag onto frag list. */
pbuf_hdr,
ip_flags,
frag_offset,
frag_size,
pfrag_list,
perr);
frag_done = DEF_YES;
}
}
}
}
if (frag_done != DEF_YES) { /* If NOT done, adv to next frag list. */
pfrag_list = (NET_BUF *)pfrag_list_buf_hdr->NextPrimListPtr;
}
} else { /* Else add new frag list (see Note #2d). */
pfrag = NetIP_RxPktFragListAdd(pbuf,
pbuf_hdr,
ip_flags,
frag_offset,
frag_size,
perr);
frag_done = DEF_YES;
}
}
return (pfrag);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragListAdd()
*
* Description : (1) Add fragment as new fragment list at end of Fragment Lists :
*
* (a) Get fragment reassembly timer
* (b) Insert fragment into Fragment Lists
* (c) Update fragment list reassembly calculations
*
*
* Argument(s) : pbuf Pointer to network buffer that received fragment.
* ---- Argument checked in NetIP_Rx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Rx().
*
* frag_ip_flags Fragment IP header flags.
* ------------- Argument validated in NetIP_RxPktFragReasm().
*
* frag_offset Fragment offset.
*
* frag_size Fragment size (in octets).
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_RX_FRAG_REASM Fragment reassembly in progress.
* NET_IP_ERR_RX_FRAG_DISCARD Fragment discarded.
* NET_IP_ERR_RX_FRAG_OFFSET Invalid fragment offset.
* NET_IP_ERR_RX_FRAG_SIZE Invalid fragment size.
*
* - RETURNED BY NetIP_RxPktFragListUpdate() : -
* NET_IP_ERR_RX_FRAG_LEN_TOT Invalid fragment datagram total IP length.
*
* Return(s) : Pointer to NULL, if fragment added as new fragment list.
*
* Pointer to fragment buffer, for any fragment discard error.
*
* Caller(s) : NetIP_RxPktFragReasm().
*
* Note(s) : (2) (a) RFC #791, Section 3.2 'Fragmentation and Reassembly' states that "if an internet
* datagram is fragmented" :
*
* (1) (A) "Fragments are counted in units of 8 octets."
* (B) "The minimum fragment is 8 octets."
*
* (2) (A) However, this CANNOT apply "if this is the last fragment" ...
* (1) "(that is the more fragments field is zero)"; ...
* (B) Which may be of ANY size.
*
* See also 'net_ip.h IP FRAGMENTATION DEFINES Note #1a'.
*
* (b) RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly Procedure'
* states that "if no other fragment with [identical] buffer identifier[s] is [available]
* then [new] reassembly resources are allocated".
*
* (3) During fragment list insertion, some fragment buffer controls were previously initialized
* in NetBuf_Get() when the packet was received at the network interface layer. These buffer
* controls do NOT need to be re-initialized but are shown for completeness.
*********************************************************************************************************
*/
static NET_BUF *NetIP_RxPktFragListAdd (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT16U frag_ip_flags,
CPU_INT16U frag_offset,
CPU_INT16U frag_size,
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 ip_flag_frags_more;
CPU_INT16U frag_size_min;
NET_ERR tmr_err;
NET_BUF *pfrag;
NET_BUF_HDR *pfrag_list_tail_buf_hdr;
/*$PAGE*/
/* ------------------- VALIDATE FRAG ------------------ */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (frag_offset > NET_IP_HDR_FRAG_OFFSET_MAX) {
NET_CTR_ERR_INC(NetIP_ErrRxFragOffsetCtr);
*perr = NET_IP_ERR_RX_FRAG_OFFSET;
return (pbuf);
}
#endif
ip_flag_frags_more = DEF_BIT_IS_SET(frag_ip_flags, NET_IP_HDR_FLAG_FRAG_MORE);
frag_size_min = (ip_flag_frags_more == DEF_YES) ? NET_IP_FRAG_SIZE_MIN_FRAG_MORE
: NET_IP_FRAG_SIZE_MIN_FRAG_LAST;
if (frag_size < frag_size_min) { /* See Note #2a. */
NET_CTR_ERR_INC(NetIP_ErrRxFragSizeCtr);
*perr = NET_IP_ERR_RX_FRAG_SIZE;
return (pbuf);
}
if (frag_size > NET_IP_FRAG_SIZE_MAX) {
NET_CTR_ERR_INC(NetIP_ErrRxFragSizeCtr);
*perr = NET_IP_ERR_RX_FRAG_SIZE;
return (pbuf);
}
/* ------------------- GET FRAG TMR ------------------- */
pbuf_hdr->TmrPtr = NetTmr_Get((void *) pbuf,
(CPU_FNCT_PTR) NetIP_RxPktFragTimeout,
(NET_TMR_TICK) NetIP_FragReasmTimeout_tick,
(CPU_INT16U ) NET_TMR_FLAG_NONE,
(NET_ERR *)&tmr_err);
if (tmr_err != NET_TMR_ERR_NONE) { /* If tmr unavail, discard frag. */
*perr = NET_IP_ERR_RX_FRAG_DISCARD;
return (pbuf);
}
/* ------------ INSERT FRAG INTO FRAG LISTS ----------- */
if (NetIP_FragReasmListsTail != (NET_BUF *)0) { /* If frag lists NOT empty, insert @ tail. */
pbuf_hdr->PrevPrimListPtr = (void *) NetIP_FragReasmListsTail;
pfrag_list_tail_buf_hdr = (NET_BUF_HDR *)&NetIP_FragReasmListsTail->Hdr;
pfrag_list_tail_buf_hdr->NextPrimListPtr = (void *) pbuf;
NetIP_FragReasmListsTail = (NET_BUF *) pbuf;
} else { /* Else add frag as first frag list. */
NetIP_FragReasmListsHead = (NET_BUF *)pbuf;
NetIP_FragReasmListsTail = (NET_BUF *)pbuf;
pbuf_hdr->PrevPrimListPtr = (void *)0;
}
#if 0 /* Init'd in NetBuf_Get() [see Note #3]. */
pbuf_hdr->NextPrimListPtr = (void *)0;
pbuf_hdr->PrevBufPtr = (void *)0;
pbuf_hdr->NextBufPtr = (void *)0;
pbuf_hdr->IP_FragSizeTot = NET_IP_FRAG_SIZE_NONE;
pbuf_hdr->IP_FragSizeCur = 0;
#endif
/* ----------------- UPDATE FRAG CALCS ---------------- */
NetIP_RxPktFragListUpdate(pbuf,
pbuf_hdr,
frag_ip_flags,
frag_offset,
frag_size,
perr);
if (*perr != NET_IP_ERR_NONE) {
return ((NET_BUF *)0);
}
*perr = NET_IP_ERR_RX_FRAG_REASM;
pfrag = (NET_BUF *)0;
return (pfrag);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragListInsert()
*
* Description : Insert fragment into corresponding fragment list.
*
* (1) (a) Fragments are sorted into fragment lists by fragment offset.
*
* See Notes #2a3 & #2b3.
*
* (b) Although RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly
* Procedure' states that "in the case that two or more fragments contain the same data
* either identically or through a partial overlap ... [the IP fragmentation reassembly
* algorithm should] use the more recently arrived copy in the data buffer and datagram
* delivered"; in order to avoid the complexity of sequencing received fragments with
* duplicate data that overlap multiple previously-received fragments' data, duplicate
* & overlap fragments are discarded :
*
* (1) Duplicate fragments are discarded. A fragment is a duplicate of a fragment already
* in the fragment list if both fragments have identical fragment offset & size values.
*
* (2) Overlap fragments are discarded & the entire Fragmented Datagram is also discarded.
* A fragment is an overlap fragment if any portion of its fragment data overlaps any
* other fragment's data :
*
* (A) [Fragment offset] < [(Any other fragment offset * FRAG_OFFSET_SIZE) +
* Any other fragment size ]
*
* (B) [(Fragment offset * FRAG_OFFSET_SIZE) + Fragment size] > [Any other fragment offset]
*
*
* See also 'net_tcp.c NetTCP_RxPktConnHandlerRxQ_Conn() Note #2a3'.
*
*
* Argument(s) : pbuf Pointer to network buffer that received fragment.
* ---- Argument checked in NetIP_Rx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Rx().
*
* frag_ip_flags Fragment IP header flags.
* ------------- Argument validated in NetIP_RxPktFragReasm().
*
* frag_offset Fragment offset.
*
* frag_size Fragment size (in octets).
*
* pfrag_list Pointer to fragment list head buffer.
* ---------- Argument validated in NetIP_RxPktFragReasm().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_RX_FRAG_REASM Fragment reassembly in progress.
* NET_IP_ERR_RX_FRAG_DISCARD Fragment discarded.
* NET_IP_ERR_RX_FRAG_OFFSET Invalid fragment offset.
* NET_IP_ERR_RX_FRAG_SIZE Invalid fragment size.
*
* -- RETURNED BY NetIP_RxPktFragListChkComplete() : -
* NET_IP_ERR_RX_FRAG_COMPLETE Datagram complete; fragments reassembled.
* NET_IP_ERR_RX_FRAG_SIZE_TOT Invalid fragmented datagram total size.
*
* ---- RETURNED BY NetIP_RxPktFragListUpdate() : ----
* -- RETURNED BY NetIP_RxPktFragListChkComplete() : -
* NET_IP_ERR_RX_FRAG_LEN_TOT Invalid fragment datagram total IP length.
*
* Return(s) : Pointer to reassembled datagram, if fragment reassembly complete.
*
* Pointer to NULL, if fragment reassembly in progress.
*
* Pointer to fragment buffer, for any fragment discard error.
*
* Caller(s) : NetIP_RxPktFragReasm().
*$PAGE*
* Note(s) : (2) (a) RFC #791, Section 3.2 'Fragmentation and Reassembly' states that "if an internet
* datagram is fragmented" :
*
* (1) (A) (1) "Fragments are counted in units of 8 octets."
* (2) "The minimum fragment is 8 octets."
*
* (B) (1) However, this CANNOT apply "if this is the last fragment" ...
* (a) "(that is the more fragments field is zero)"; ...
* (2) Which may be of ANY size.
*
* See also 'net_ip.h IP FRAGMENTATION DEFINES Note #1a'.
*
* (2) "Fragments ... data portion must be ... on 8 octet boundaries."
*
* (3) "The Fragment Offset field identifies the fragment location, relative to the
* beginning of the original unfragmented datagram."
*
* (b) RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly Procedure'
* states that :
*
* (1) (A) "If this is the first fragment" ...
* (1) "(that is the fragment offset is zero)", ...
* (B) "this header is placed in the header buffer."
*
* (2) "Some [IP] options are copied [in every fragment], but others remain with
* the first fragment only."
*
* (3) "The data from the fragment is placed in the data buffer according to its
* fragment offset and length."
*
* See also Note #2a3.
*
* (3) Assumes ALL fragments in fragment lists have previously been validated for buffer &
* IP header fields.
*
* (4) During fragment list insertion, some fragment buffer controls were previously
* initialized in NetBuf_Get() when the packet was received at the network interface
* layer. These buffer controls do NOT need to be re-initialized but are shown for
* completeness.
*********************************************************************************************************
*/
/*$PAGE*/
static NET_BUF *NetIP_RxPktFragListInsert (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT16U frag_ip_flags,
CPU_INT16U frag_offset,
CPU_INT16U frag_size,
NET_BUF *pfrag_list,
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 ip_flag_frags_more;
CPU_BOOLEAN frag_insert_done;
CPU_BOOLEAN frag_list_discard;
CPU_INT16U frag_offset_actual;
CPU_INT16U frag_list_cur_frag_offset;
CPU_INT16U frag_list_cur_frag_offset_actual;
CPU_INT16U frag_list_prev_frag_offset;
CPU_INT16U frag_list_prev_frag_offset_actual;
CPU_INT16U frag_size_min;
CPU_INT16U frag_size_cur;
NET_BUF *pfrag;
NET_BUF *pfrag_list_prev_buf;
NET_BUF *pfrag_list_cur_buf;
NET_BUF *pfrag_list_prev_list;
NET_BUF *pfrag_list_next_list;
NET_BUF_HDR *pfrag_list_buf_hdr;
NET_BUF_HDR *pfrag_list_prev_buf_hdr;
NET_BUF_HDR *pfrag_list_cur_buf_hdr;
NET_BUF_HDR *pfrag_list_prev_list_buf_hdr;
NET_BUF_HDR *pfrag_list_next_list_buf_hdr;
NET_TMR *ptmr;
NET_ERR err;
/* ------------------- VALIDATE FRAG ------------------ */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (frag_offset > NET_IP_HDR_FRAG_OFFSET_MAX) {
NET_CTR_ERR_INC(NetIP_ErrRxFragOffsetCtr);
*perr = NET_IP_ERR_RX_FRAG_OFFSET;
return (pbuf);
}
#endif
ip_flag_frags_more = DEF_BIT_IS_SET(frag_ip_flags, NET_IP_HDR_FLAG_FRAG_MORE);
frag_size_min = (ip_flag_frags_more == DEF_YES) ? NET_IP_FRAG_SIZE_MIN_FRAG_MORE
: NET_IP_FRAG_SIZE_MIN_FRAG_LAST;
if (frag_size < frag_size_min) { /* See Note #2a1. */
NET_CTR_ERR_INC(NetIP_ErrRxFragSizeCtr);
*perr = NET_IP_ERR_RX_FRAG_SIZE;
return (pbuf);
}
if (frag_size > NET_IP_FRAG_SIZE_MAX) {
NET_CTR_ERR_INC(NetIP_ErrRxFragSizeCtr);
*perr = NET_IP_ERR_RX_FRAG_SIZE;
return (pbuf);
}
/*$PAGE*/
/* ------- INSERT FRAG INTO FRAG LISTS -------- */
frag_insert_done = DEF_NO;
pfrag_list_cur_buf = (NET_BUF *) pfrag_list;
pfrag_list_cur_buf_hdr = (NET_BUF_HDR *)&pfrag_list_cur_buf->Hdr;
while (frag_insert_done == DEF_NO) {
frag_list_cur_frag_offset = pfrag_list_cur_buf_hdr->IP_Flags_FragOffset & NET_IP_HDR_FRAG_OFFSET_MASK;
if (frag_offset > frag_list_cur_frag_offset) { /* While frag offset > cur frag offset, ... */
if (pfrag_list_cur_buf_hdr->NextBufPtr != (NET_BUF *)0) { /* ... adv to next frag in list. */
pfrag_list_cur_buf = (NET_BUF *) pfrag_list_cur_buf_hdr->NextBufPtr;
pfrag_list_cur_buf_hdr = (NET_BUF_HDR *)&pfrag_list_cur_buf->Hdr;
} else { /* If @ last frag in list, append frag @ end. */
frag_offset_actual = frag_offset * NET_IP_FRAG_SIZE_UNIT;
frag_list_cur_frag_offset_actual = ( frag_list_cur_frag_offset * NET_IP_FRAG_SIZE_UNIT )
+ (pfrag_list_cur_buf_hdr->IP_TotLen - pfrag_list_cur_buf_hdr->IP_HdrLen);
if (frag_offset_actual >= frag_list_cur_frag_offset_actual) { /* If frag does NOT overlap, ... */
/* ... append @ end of frag list. */
pbuf_hdr->PrevBufPtr = (void *)pfrag_list_cur_buf;
#if 0 /* Init'd in NetBuf_Get() [see Note #4]. */
pbuf_hdr->NextBufPtr = (void *)0;
pbuf_hdr->PrevPrimListPtr = (void *)0;
pbuf_hdr->NextPrimListPtr = (void *)0;
pbuf_hdr->TmrPtr = (NET_TMR *)0;
pbuf_hdr->IP_FragSizeTot = NET_IP_FRAG_SIZE_NONE;
pbuf_hdr->IP_FragSizeCur = 0;
#endif
pfrag_list_cur_buf_hdr->NextBufPtr = (void *)pbuf;
pfrag_list_buf_hdr = &pfrag_list->Hdr;
NetIP_RxPktFragListUpdate(pfrag_list, /* Update frag list reasm calcs. */
pfrag_list_buf_hdr,
frag_ip_flags,
frag_offset,
frag_size,
perr);
if (*perr != NET_IP_ERR_NONE) {
return ((NET_BUF *)0);
}
/* Chk frag list reasm complete. */
pfrag = NetIP_RxPktFragListChkComplete(pfrag_list,
pfrag_list_buf_hdr,
perr);
} else { /* Else discard overlap frag & datagram. */
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, &err);
NET_CTR_ERR_INC(NetIP_ErrRxFragDiscardedCtr);
pfrag = pbuf;
*perr = NET_IP_ERR_RX_FRAG_DISCARD;
}
frag_insert_done = DEF_YES;
}
} else if (frag_offset < frag_list_cur_frag_offset) { /* If frag offset < cur frag offset, ... */
/* ... insert frag into frag list. */
frag_list_discard = DEF_NO;
frag_offset_actual = (frag_offset * NET_IP_FRAG_SIZE_UNIT) + frag_size;
frag_list_cur_frag_offset_actual = frag_list_cur_frag_offset * NET_IP_FRAG_SIZE_UNIT;
if (frag_offset_actual > frag_list_cur_frag_offset_actual) {/* If frag overlaps with next frag, ... */
frag_list_discard = DEF_YES; /* ... discard frag & datagram (see Note #1b2). */
} else if (pfrag_list_cur_buf_hdr->PrevBufPtr != (void *)0) {
pfrag_list_prev_buf = (NET_BUF *) pfrag_list_cur_buf_hdr->PrevBufPtr;
pfrag_list_prev_buf_hdr = (NET_BUF_HDR *)&pfrag_list_prev_buf->Hdr;
frag_offset_actual = frag_offset * NET_IP_FRAG_SIZE_UNIT;
frag_list_prev_frag_offset = pfrag_list_prev_buf_hdr->IP_Flags_FragOffset & NET_IP_HDR_FRAG_OFFSET_MASK;
frag_list_prev_frag_offset_actual = ( frag_list_prev_frag_offset * NET_IP_FRAG_SIZE_UNIT )
+ (pfrag_list_prev_buf_hdr->IP_TotLen - pfrag_list_prev_buf_hdr->IP_HdrLen);
/* If frag overlaps with prev frag, ... */
if (frag_offset_actual < frag_list_prev_frag_offset_actual) {
frag_list_discard = DEF_YES; /* ... discard frag & datagram (see Note #1b2). */
}
}
/*$PAGE*/
if (frag_list_discard == DEF_NO) { /* If frag does NOT overlap, ... */
/* ... insert into frag list. */
pbuf_hdr->PrevBufPtr = (void *)pfrag_list_cur_buf_hdr->PrevBufPtr;
pbuf_hdr->NextBufPtr = (void *)pfrag_list_cur_buf;
if (pbuf_hdr->PrevBufPtr != (void *)0) { /* Insert pbuf between prev & cur bufs. */
pfrag_list_prev_buf = (NET_BUF *) pbuf_hdr->PrevBufPtr;
pfrag_list_prev_buf_hdr = (NET_BUF_HDR *)&pfrag_list_prev_buf->Hdr;
pfrag_list_prev_buf_hdr->NextBufPtr = (void *) pbuf;
pfrag_list_cur_buf_hdr->PrevBufPtr = (void *) pbuf;
#if 0 /* Init'd in NetBuf_Get() [see Note #4]. */
pbuf_hdr->PrevPrimListPtr = (void *)0;
pbuf_hdr->NextPrimListPtr = (void *)0;
pbuf_hdr->TmrPtr = (NET_TMR *)0;
pbuf_hdr->IP_FragSizeTot = NET_IP_FRAG_SIZE_NONE;
pbuf_hdr->IP_FragSizeCur = 0;
#endif
} else { /* Else pbuf is new frag list head. */
pfrag_list = pbuf;
/* Move frag list head info to cur buf ... */
/* ... (see Note #2b1). */
pbuf_hdr->PrevPrimListPtr = pfrag_list_cur_buf_hdr->PrevPrimListPtr;
pbuf_hdr->NextPrimListPtr = pfrag_list_cur_buf_hdr->NextPrimListPtr;
pbuf_hdr->TmrPtr = pfrag_list_cur_buf_hdr->TmrPtr;
pbuf_hdr->IP_FragSizeTot = pfrag_list_cur_buf_hdr->IP_FragSizeTot;
pbuf_hdr->IP_FragSizeCur = pfrag_list_cur_buf_hdr->IP_FragSizeCur;
pfrag_list_cur_buf_hdr->PrevBufPtr = (void *)pbuf;
pfrag_list_cur_buf_hdr->PrevPrimListPtr = (void *)0;
pfrag_list_cur_buf_hdr->NextPrimListPtr = (void *)0;
pfrag_list_cur_buf_hdr->TmrPtr = (NET_TMR *)0;
pfrag_list_cur_buf_hdr->IP_FragSizeTot = NET_IP_FRAG_SIZE_NONE;
pfrag_list_cur_buf_hdr->IP_FragSizeCur = 0;
/* Point tmr to new frag list head. */
ptmr = (NET_TMR *)pbuf_hdr->TmrPtr;
ptmr->Obj = (void *)pbuf;
/* Point prev frag list to new frag list head. */
pfrag_list_prev_list = (NET_BUF *)pbuf_hdr->PrevPrimListPtr;
if (pfrag_list_prev_list != (NET_BUF *)0) {
pfrag_list_prev_list_buf_hdr = (NET_BUF_HDR *)&pfrag_list_prev_list->Hdr;
pfrag_list_prev_list_buf_hdr->NextPrimListPtr = (void *) pbuf;
} else {
NetIP_FragReasmListsHead = (NET_BUF *) pbuf;
}
/* Point next frag list to new frag list head. */
pfrag_list_next_list = (NET_BUF *)pbuf_hdr->NextPrimListPtr;
if (pfrag_list_next_list != (NET_BUF *)0) {
pfrag_list_next_list_buf_hdr = (NET_BUF_HDR *)&pfrag_list_next_list->Hdr;
pfrag_list_next_list_buf_hdr->PrevPrimListPtr = (void *) pbuf;
} else {
NetIP_FragReasmListsTail = (NET_BUF *) pbuf;
}
}
pfrag_list_buf_hdr = &pfrag_list->Hdr;
NetIP_RxPktFragListUpdate(pfrag_list, /* Update frag list reasm calcs. */
pfrag_list_buf_hdr,
frag_ip_flags,
frag_offset,
frag_size,
perr);
if (*perr != NET_IP_ERR_NONE) {
return ((NET_BUF *)0);
}
/* Chk frag list reasm complete. */
pfrag = NetIP_RxPktFragListChkComplete(pfrag_list,
pfrag_list_buf_hdr,
perr);
} else { /* Else discard overlap frag & datagram ... */
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, &err); /* ... (see Note #1b2). */
NET_CTR_ERR_INC(NetIP_ErrRxFragDiscardedCtr);
pfrag = pbuf;
*perr = NET_IP_ERR_RX_FRAG_DISCARD;
}
frag_insert_done = DEF_YES;
/*$PAGE*/
} else { /* Else if frag offset = cur frag offset, ... */
NET_CTR_ERR_INC(NetIP_ErrRxFragDiscardedCtr);
pfrag = pbuf;
*perr = NET_IP_ERR_RX_FRAG_DISCARD; /* ... discard duplicate frag (see Note #1b1). */
frag_size_cur = pfrag_list_cur_buf_hdr->IP_TotLen - pfrag_list_cur_buf_hdr->IP_HdrLen;
if (frag_size != frag_size_cur) { /* If frag size != cur frag size, ... */
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, &err); /* ... discard overlap frag datagram ... */
/* ... (see Note #1b2). */
}
frag_insert_done = DEF_YES;
}
}
return (pfrag);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragListRemove()
*
* Description : (1) Remove fragment list from Fragment Lists :
*
* (a) Free fragment reassembly timer
* (b) Remove fragment list from Fragment Lists
* (c) Clear buffer's fragment pointers
*
*
* Argument(s) : pfrag_list Pointer to fragment list head buffer.
* ---------- Argument validated in NetIP_RxPktFragListDiscard(),
* NetIP_RxPktFragListChkComplete().
*
* tmr_free Indicate whether to free network timer :
*
* DEF_YES Free network timer for fragment list discard.
* DEF_NO Do NOT free network timer for fragment list discard
* [Freed by NetTmr_TaskHandler()
* via NetIP_RxPktFragListDiscard()].
*
* Return(s) : none.
*
* Caller(s) : NetIP_RxPktFragListDiscard(),
* NetIP_RxPktFragListChkComplete().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetIP_RxPktFragListRemove (NET_BUF *pfrag_list,
CPU_BOOLEAN tmr_free)
{
NET_BUF *pfrag_list_prev_list;
NET_BUF *pfrag_list_next_list;
NET_BUF_HDR *pfrag_list_prev_list_buf_hdr;
NET_BUF_HDR *pfrag_list_next_list_buf_hdr;
NET_BUF_HDR *pfrag_list_buf_hdr;
NET_TMR *ptmr;
pfrag_list_buf_hdr = &pfrag_list->Hdr;
/* ------------------ FREE FRAG TMR ------------------- */
if (tmr_free == DEF_YES) {
ptmr = pfrag_list_buf_hdr->TmrPtr;
if (ptmr != (NET_TMR *)0) {
NetTmr_Free(ptmr);
}
}
/* --------- REMOVE FRAG LIST FROM FRAG LISTS --------- */
pfrag_list_prev_list = (NET_BUF *)pfrag_list_buf_hdr->PrevPrimListPtr;
pfrag_list_next_list = (NET_BUF *)pfrag_list_buf_hdr->NextPrimListPtr;
/* Point prev frag list to next frag list. */
if (pfrag_list_prev_list != (NET_BUF *)0) {
pfrag_list_prev_list_buf_hdr = (NET_BUF_HDR *)&pfrag_list_prev_list->Hdr;
pfrag_list_prev_list_buf_hdr->NextPrimListPtr = (void *) pfrag_list_next_list;
} else {
NetIP_FragReasmListsHead = (NET_BUF *) pfrag_list_next_list;
}
/* Point next frag list to prev frag list. */
if (pfrag_list_next_list != (NET_BUF *)0) {
pfrag_list_next_list_buf_hdr = (NET_BUF_HDR *)&pfrag_list_next_list->Hdr;
pfrag_list_next_list_buf_hdr->PrevPrimListPtr = (void *) pfrag_list_prev_list;
} else {
NetIP_FragReasmListsTail = (NET_BUF *) pfrag_list_prev_list;
}
/* ---------------- CLR BUF FRAG PTRS ----------------- */
pfrag_list_buf_hdr->PrevPrimListPtr = (void *)0;
pfrag_list_buf_hdr->NextPrimListPtr = (void *)0;
pfrag_list_buf_hdr->TmrPtr = (NET_TMR *)0;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragListDiscard()
*
* Description : Discard fragment list from Fragment Lists.
*
* Argument(s) : pfrag_list Pointer to fragment list head buffer.
* ---------- Argument validated in NetIP_RxPktFragListInsert(),
* NetIP_RxPktFragListChkComplete(),
* NetIP_RxPktFragListDiscard().
*
* tmr_free Indicate whether to free network timer :
*
* DEF_YES Free network timer for fragment list discard.
* DEF_NO Do NOT free network timer for fragment list discard
* [Freed by NetTmr_TaskHandler()].
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_RX_FRAG_DISCARD Fragment list discarded.
*
* Return(s) : none.
*
* Caller(s) : NetIP_RxPktFragListInsert(),
* NetIP_RxPktFragListChkComplete(),
* NetIP_RxPktFragListTimeout().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetIP_RxPktFragListDiscard (NET_BUF *pfrag_list,
CPU_BOOLEAN tmr_free,
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_ERR err;
NetIP_RxPktFragListRemove(pfrag_list, tmr_free); /* Remove frag list from Frag Lists. */
NetIP_RxPktDiscard(pfrag_list, &err); /* Discard every frag buf in frag list. */
NET_CTR_ERR_INC(NetIP_ErrRxFragDatagramDiscardedCtr); /* Inc discarded frag'd datagram ctr. */
*perr = NET_IP_ERR_RX_FRAG_DISCARD;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragListUpdate()
*
* Description : Update fragment list reassembly calculations.
*
* Argument(s) : pfrag_list_buf_hdr Pointer to fragment list head buffer's header.
* ------------------ Argument validated in NetIP_RxPktFragListAdd(),
* NetIP_RxPktFragListInsert().
*
* frag_ip_flags Fragment IP header flags.
* ------------- Argument validated in NetIP_RxPktFragListAdd(),
* NetIP_RxPktFragListInsert().
*
* frag_offset Fragment offset.
* ----------- Argument validated in NetIP_RxPktFragListAdd(),
* NetIP_RxPktFragListInsert().
*
* frag_size Fragment size (in octets).
* --------- Argument validated in NetIP_RxPktFragListAdd(),
* NetIP_RxPktFragListInsert().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Fragment list reassembly calculations
* successfully updated.
* NET_IP_ERR_RX_FRAG_LEN_TOT Invalid fragment datagram total IP length.
*
* Return(s) : none.
*
* Caller(s) : NetIP_RxPktFragListAdd(),
* NetIP_RxPktFragListInsert().
*
* Note(s) : (1) (a) RFC #791, Section 3.2 'Fragmentation and Reassembly' states that "fragments ... data
* portion ... allows" up to :
*
* (1) "2**13 = 8192 fragments" ...
* (2) "of 8 octets each" ...
* (3) "for a total of 65,536 [sic] octets."
*
* (b) RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly Procedure'
* states that :
*
* (1) "If this is the last fragment" ...
* (A) "(that is the more fragments field is zero)"; ...
*
* (2) "The total data length is computed."
*
* (2) To avoid possible integer arithmetic overflow, the fragmentation arithmetic result MUST
* be declared as an integer data type with a greater resolution -- i.e. greater number of
* bits -- than the fragmentation arithmetic operands' data type(s).
*********************************************************************************************************
*/
static void NetIP_RxPktFragListUpdate (NET_BUF *pfrag_list,
NET_BUF_HDR *pfrag_list_buf_hdr,
CPU_INT16U frag_ip_flags,
CPU_INT16U frag_offset,
CPU_INT16U frag_size,
NET_ERR *perr)
{
CPU_BOOLEAN ip_flag_frags_more;
CPU_INT32U frag_size_tot; /* See Note #2. */
NET_ERR err;
pfrag_list_buf_hdr->IP_FragSizeCur += frag_size;
ip_flag_frags_more = DEF_BIT_IS_SET(frag_ip_flags, NET_IP_HDR_FLAG_FRAG_MORE);
if (ip_flag_frags_more != DEF_YES) { /* If 'More Frags' NOT set (see Note #1b1A), ... */
/* ... calc frag tot size (see Note #1b2). */
frag_size_tot = ((CPU_INT32U)frag_offset * NET_IP_FRAG_SIZE_UNIT) + (CPU_INT32U)frag_size;
if (frag_size_tot > NET_IP_TOT_LEN_MAX) { /* If frag tot size > IP tot len max, ... */
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, &err); /* ... discard ovf'd frag datagram (see Note #1a3). */
*perr = NET_IP_ERR_RX_FRAG_LEN_TOT;
return;
}
pfrag_list_buf_hdr->IP_FragSizeTot = (CPU_INT16U)frag_size_tot;
}
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragListChkComplete()
*
* Description : Check if fragment list complete; i.e. fragmented datagram reassembled.
*
* Argument(s) : pfrag_list Pointer to fragment list head buffer.
* ---------- Argument validated in NetIP_RxPktFragListInsert().
*
* pfrag_list_buf_hdr Pointer to fragment list head buffer's header.
* ------------------ Argument validated in NetIP_RxPktFragListInsert().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_RX_FRAG_COMPLETE Datagram complete; fragments reassembled.
* NET_IP_ERR_RX_FRAG_REASM Fragments in reassembly progress.
* NET_IP_ERR_RX_FRAG_SIZE_TOT Invalid fragmented datagram total size.
* NET_IP_ERR_RX_FRAG_LEN_TOT Invalid fragment datagram total IP length.
*
* - RETURNED BY NetIP_RxPktFragListDiscard() : -
* NET_IP_ERR_RX_FRAG_DISCARD Fragment list discarded.
*
* Return(s) : Pointer to reassembled datagram, if fragment reassembly complete.
*
* Pointer to NULL, if fragment reassembly in progress.
* OR
* for any fragment discard error.
*
* Caller(s) : NetIP_RxPktFragListInsert().
*
* Note(s) : (1) (a) RFC #791, Section 3.2 'Fragmentation and Reassembly' states that :
*
* (1) "Fragments ... data portion ... allows" up to :
* (A) "2**13 = 8192 fragments" ...
* (B) "of 8 octets each" ...
* (C) "for a total of 65,536 [sic] octets."
*
* (2) "The header is counted in the total length and not in the fragments."
*
* (b) RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly
* Procedure' states that :
*
* (1) "If this fragment completes the datagram ... then the datagram is sent to
* the next step in datagram processing."
*
* (2) "Otherwise the timer is set to" :
* (A) "the maximum of the current timer value" ...
* (B) "and the value of the time to live field from this fragment."
* (1) #### However, since IP headers' Time-To-Live (TTL) field does NOT
* directly correlate to a specific timeout value in seconds, this
* requirement is NOT implemented.
*
* (2) To avoid possible integer arithmetic overflow, the fragmentation arithmetic result
* MUST be declared as an integer data type with a greater resolution -- i.e. greater
* number of bits -- than the fragmentation arithmetic operands' data type(s).
*********************************************************************************************************
*/
/*$PAGE*/
static NET_BUF *NetIP_RxPktFragListChkComplete (NET_BUF *pfrag_list,
NET_BUF_HDR *pfrag_list_buf_hdr,
NET_ERR *perr)
{
#if ((NET_CTR_CFG_STAT_EN == DEF_ENABLED) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_INT32U frag_tot_len; /* See Note #2. */
NET_BUF *pfrag;
NET_ERR err;
/* If tot frag size complete, ... */
if (pfrag_list_buf_hdr->IP_FragSizeCur == pfrag_list_buf_hdr->IP_FragSizeTot) {
/* Calc frag IP tot len (see Note #1a2). */
frag_tot_len = (CPU_INT32U)pfrag_list_buf_hdr->IP_HdrLen + (CPU_INT32U)pfrag_list_buf_hdr->IP_FragSizeTot;
if (frag_tot_len > NET_IP_TOT_LEN_MAX) { /* If tot frag len > IP tot len max, ... */
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, &err); /* ... discard ovf'd frag datagram (see Note #1a1C).*/
*perr = NET_IP_ERR_RX_FRAG_LEN_TOT;
return ((NET_BUF *)0);
}
NetIP_RxPktFragListRemove(pfrag_list, DEF_YES);
NET_CTR_STAT_INC(NetIP_StatRxFragDatagramReasmCtr);
pfrag = pfrag_list; /* ... rtn reasm'd datagram (see Note #1b1). */
*perr = NET_IP_ERR_RX_FRAG_COMPLETE;
/* If cur frag size > tot frag size, ... */
} else if (pfrag_list_buf_hdr->IP_FragSizeCur > pfrag_list_buf_hdr->IP_FragSizeTot) {
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, perr); /* ... discard ovf'd frag datagram. */
*perr = NET_IP_ERR_RX_FRAG_SIZE_TOT;
return ((NET_BUF *)0);
} else { /* Else reset frag tmr (see Note #1b2A). */
NetTmr_Set((NET_TMR *) pfrag_list_buf_hdr->TmrPtr,
(CPU_FNCT_PTR) NetIP_RxPktFragTimeout,
(NET_TMR_TICK) NetIP_FragReasmTimeout_tick,
(NET_ERR *)&err);
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (err != NET_TMR_ERR_NONE) {
NetIP_RxPktFragListDiscard(pfrag_list, DEF_YES, perr);
return ((NET_BUF *)0);
}
#endif
*perr = NET_IP_ERR_RX_FRAG_REASM;
pfrag = (NET_BUF *)0;
}
return (pfrag);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktFragTimeout()
*
* Description : Discard fragment list on fragment reassembly timeout.
*
* Argument(s) : pfrag_list_timeout Pointer to network buffer fragment reassembly list (see Note #1b).
*
* Return(s) : none.
*
* Caller(s) : Referenced in NetIP_RxPktFragListAdd().
*
* Note(s) : (1) RFC #791, Section 3.2 'Fragmentation and Reassembly : An Example Reassembly Procedure'
* states that :
*
* (a) "If the [IP fragments' reassembly] timer runs out," ...
* (b) "the [sic] all reassembly resources for this buffer identifier are released."
*
* (2) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]'
* type functions -- even though network timer API functions cast expiration functions
* to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
* (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a
* pointer to an object ... may be converted to a pointer to a different object
* ... [but] if the resulting pointer is not correctly aligned ... the behavior
* is undefined".
*
* And since compilers may NOT correctly convert 'void' pointers to non-'void'
* pointer arguments, network timer expiration functions MUST avoid incorrect
* pointer conversion behavior between 'void' pointer parameters & non-'void'
* pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
* (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted
* to or from a pointer to any ... object ... A pointer to any ... object ...
* may be converted to a pointer to void and back again; the result shall
* compare equal to the original pointer".
*
* (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
* network object pointer objects, network timer expiration functions MUST :
*
* (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); & ...
* (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
* (A) ... in this case, a 'NET_BUF' pointer.
*
* See also 'net_tmr.c NetTmr_Get() Note #3'.
*
* (3) This function is a network timer expiration function :
*
* (a) Clear the timer pointer; ...
* (1) Cleared in NetIP_RxPktFragListRemove() via NetIP_RxPktFragListDiscard().
*
* (b) but do NOT re-free the timer.
*
* (4) (a) RFC #792, Section 'Time Exceeded Message' states that :
*
* (1) "if a host reassembling a fragmented datagram cannot complete the reassembly
* due to missing fragments within its time limit" ...
* (2) (A) "it discards the datagram," ...
* (B) "and it may send a time exceeded message."
*
* (b) MUST send ICMP 'Time Exceeded' error message BEFORE NetIP_RxPktFragListDiscard()
* frees fragment buffers.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_RxPktFragTimeout (void *pfrag_list_timeout)
{
#if ((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_BUF *pfrag_list;
NET_ERR err;
pfrag_list = (NET_BUF *)pfrag_list_timeout; /* See Note #2b2A. */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
/* ------------------ VALIDATE PTR -------------------- */
if (pfrag_list == (NET_BUF *)0) {
NET_CTR_ERR_INC(NetIP_ErrNullPtrCtr);
return;
}
/* ---------------- VALIDATE BUF USED ----------------- */
used = NetBuf_IsUsed(pfrag_list);
if (used != DEF_YES) {
NET_CTR_ERR_INC(NetIP_ErrNullPtrCtr);
return;
}
#endif
NetICMP_TxMsgErr((NET_BUF *) pfrag_list, /* Send ICMP 'Time Exceeded' err msg (see Note #4). */
(CPU_INT08U) NET_ICMP_MSG_TYPE_TIME_EXCEED,
(CPU_INT08U) NET_ICMP_MSG_CODE_TIME_EXCEED_FRAG_REASM,
(CPU_INT08U) NET_ICMP_MSG_PTR_NONE,
(NET_ERR *)&err);
/* Discard frag list (see Note #1b). */
NetIP_RxPktFragListDiscard((NET_BUF *) pfrag_list,
(CPU_BOOLEAN) DEF_NO, /* Clr but do NOT free tmr (see Note #3). */
(NET_ERR *)&err);
NET_CTR_ERR_INC(NetIP_ErrRxFragDatagramTimeoutCtr);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktDemuxDatagram()
*
* Description : Demultiplex IP datagram to appropriate ICMP, TCP, or UDP queue.
*
* Argument(s) : pbuf Pointer to network buffer that received IP datagram.
* ---- Argument checked in NetIP_Rx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Rx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
* NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type.
* NET_ERR_RX Receive error; packet discarded.
*
* ------ RETURNED BY NetICMP_Rx() : ------
* NET_ICMP_ERR_NONE ICMP message successfully demultiplexed.
*
* ------ RETURNED BY NetTCP_Rx() : -------
* NET_TCP_ERR_NONE TCP segment successfully demultiplexed.
*
* ------ RETURNED BY NetUDP_Rx() : -------
* NET_UDP_ERR_NONE UDP datagram successfully demultiplexed.
*
* Return(s) : none.
*
* Caller(s) : NetIP_Rx().
*
* Note(s) : (1) When network buffer is demultiplexed to higher-layer protocol receive, buffer's reference
* counter is NOT incremented since the IP layer does NOT maintain a reference to the buffer.
*
* (2) Default case already invalidated in NetIP_RxPktValidate(). However, the default case
* is included as an extra precaution in case 'ProtocolHdrType' is incorrectly modified.
*********************************************************************************************************
*/
static void NetIP_RxPktDemuxDatagram (NET_BUF *pbuf,
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
switch (pbuf_hdr->ProtocolHdrType) { /* Demux buf to appropriate protocol Q (see Note #1). */
case NET_PROTOCOL_TYPE_ICMP:
NetICMP_Rx(pbuf, perr);
break;
case NET_PROTOCOL_TYPE_UDP:
NetUDP_Rx(pbuf, perr);
break;
#ifdef NET_TCP_MODULE_PRESENT
case NET_PROTOCOL_TYPE_TCP:
NetTCP_Rx(pbuf, perr);
break;
#endif
case NET_PROTOCOL_TYPE_NONE:
default: /* See Note #2. */
NET_CTR_ERR_INC(Net_ErrInvalidProtocolCtr);
*perr = NET_ERR_INVALID_PROTOCOL;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_RxPktDiscard()
*
* Description : On any IP Receive errors, discard IP 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) : NetIP_Rx(),
* NetIP_RxPktFragListDiscard().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetIP_RxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr)
{
NET_CTR *pctr;
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
pctr = (NET_CTR *)&NetIP_ErrRxPktDiscardedCtr;
#else
pctr = (NET_CTR *) 0;
#endif
NetBuf_FreeBufList((NET_BUF *)pbuf,
(NET_CTR *)pctr);
*perr = NET_ERR_RX;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktValidate()
*
* Description : (1) Validate IP transmit packet parameters & options :
*
* (a) Packets with the following invalid parameters will be "silently discarded" :
*
* (1) Protocols other than supported protocols :
* (A) ICMP
* (B) TCP
* (C) UDP
*
* (2) Total Length
* (3) Type of Service (TOS) See 'net_ip.h IP HEADER TYPE OF SERVICE (TOS) DEFINES'
*
* (4) Source Address
* (A) MUST be one of the following :
* (1) This host's RFC #1122, Section 3.2.1.3
* (2) This Host RFC #1122, Section 3.2.1.3.(a)
* (3) Specified Host RFC #1122, Section 3.2.1.3.(b)
* (B) MUST NOT be one of the following :
* (1) Limited Broadcast RFC #1122, Section 3.2.1.3.(c)
* (2) Directed Broadcast RFC #1122, Section 3.2.1.3.(d)
* (3) Subnet Broadcast RFC #1122, Section 3.2.1.3.(e)
* (4) Multicast RFC #1122, Section 3.2.1.3
* (C) SHOULD NOT be one of the following :
* (1) Localhost RFC #1122, Section 3.2.1.3.(g)
*
* (5) Destination Address
* (A) MAY be one of the following :
* (1) Localhost RFC #1122, Section 3.2.1.3.(g)
* (2) Limited Broadcast RFC #1122, Section 3.2.1.3.(c)
* (3) Directed Broadcast RFC #1122, Section 3.2.1.3.(d)
* (4) Subnet Broadcast RFC #1122, Section 3.2.1.3.(e)
* (B) MUST NOT be one of the following :
* (1) This Host RFC #1122, Section 3.2.1.3.(a)
* (2) Specified Host RFC #1122, Section 3.2.1.3.(b)
*
* (6) Flags
*
* (b) The following parameters are inherently assumed to be valid :
*
* (1) Time-to-Live (TTL)
*
*$PAGE*
* Argument(s) : pbuf Pointer to network buffer to transmit IP packet.
* ---- Argument checked in NetIP_Tx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Tx().
*
* addr_src Source IP address.
*
* addr_dest Destination IP address.
*
* 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 RFC #1122, Section 3.2.1.7) :
*
* NET_IP_HDR_TTL_MIN 1 minimum TTL transmit value
* NET_IP_HDR_TTL_MAX 255 maximum TTL transmit value
* NET_IP_HDR_TTL_DFLT default TTL transmit value
* NET_IP_HDR_TTL_NONE 0 replace with default TTL
*
* 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_IP_ERR_NONE Transmit packet validated.
* NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type.
* NET_BUF_ERR_INVALID_IX Invalid or insufficient buffer index.
* NET_IP_ERR_INVALID_LEN_DATA Invalid protocol/data length.
* NET_IP_ERR_INVALID_TOS Invalid TOS.
* NET_IP_ERR_INVALID_ADDR_SRC Invalid IP source address.
* NET_IP_ERR_INVALID_ADDR_DEST Invalid IP destination address.
* NET_IP_ERR_INVALID_FLAG Invalid IP flag(s).
*
* -- RETURNED BY NetIP_TxPktValidateOpt() : --
* NET_IP_ERR_NONE IP transmit option configurations validated.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP options length.
* NET_IP_ERR_INVALID_OPT_CFG Invalid IP options configuration.
* NET_IP_ERR_INVALID_OPT_ROUTE Invalid IP route address(s).
*
* Return(s) : none.
*
* Caller(s) : NetIP_Tx().
*
* Note(s) : (2) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
*********************************************************************************************************
*/
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetIP_TxPktValidate (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
void *popts,
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_INT16U ix;
CPU_INT16U len;
CPU_INT16U flag_mask;
CPU_BOOLEAN tos_mbz;
/* ----------------- VALIDATE PROTOCOL ---------------- */
switch (pbuf_hdr->ProtocolHdrType) {
case NET_PROTOCOL_TYPE_ICMP:
ix = pbuf_hdr->ICMP_MsgIx;
len = pbuf_hdr->ICMP_MsgLen;
break;
case NET_PROTOCOL_TYPE_UDP:
case NET_PROTOCOL_TYPE_TCP:
ix = pbuf_hdr->TCP_UDP_HdrDataIx;
len = pbuf_hdr->TCP_UDP_HdrLen + (CPU_INT16U)pbuf_hdr->DataLen;
break;
case NET_PROTOCOL_TYPE_NONE:
default:
NET_CTR_ERR_INC(NetIP_ErrTxProtocolCtr);
*perr = NET_ERR_INVALID_PROTOCOL;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
if (ix == NET_BUF_IX_NONE) {
NET_CTR_ERR_INC(NetIP_ErrTxInvalidBufIxCtr);
*perr = NET_BUF_ERR_INVALID_IX;
return;
}
if (ix < NET_IP_HDR_SIZE_MAX) {
NET_CTR_ERR_INC(NetIP_ErrTxInvalidBufIxCtr);
*perr = NET_BUF_ERR_INVALID_IX;
return;
}
/* -------------- VALIDATE TOT DATA LEN --------------- */
if (len != pbuf_hdr->TotLen) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrDataLenCtr);
*perr = NET_IP_ERR_INVALID_LEN_DATA;
return;
}
/* ----------------- VALIDATE IP TOS ------------------ */
tos_mbz = DEF_BIT_IS_SET(TOS, NET_IP_HDR_TOS_MBZ_MASK);
if (tos_mbz != DEF_NO) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrTOS_Ctr);
*perr = NET_IP_ERR_INVALID_TOS;
return;
}
/*$PAGE*/
/* ------------- VALIDATE IP SRC ADDR ------------- */
/* See Note #1a4. */
if (addr_src != NetIP_AddrThisHost) { /* Chk this host's addr (see Note #1a4A1). */
if (addr_src != NET_IP_ADDR_THIS_HOST) { /* Chk 'This Host' (see Note #1a4A2). */
if ((addr_src & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
/* Chk Class-A specified host (see Note #1a4A3). */
if ((addr_src & NET_IP_ADDR_CLASS_A_MASK_HOST) !=
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
} else if ((addr_src & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
/* Chk Class-B specified host (see Note #1a4A3). */
if ((addr_src & NET_IP_ADDR_CLASS_B_MASK_HOST) !=
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
} else if ((addr_src & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
/* Chk Class-C specified host (see Note #1a4A3). */
if ((addr_src & NET_IP_ADDR_CLASS_C_MASK_HOST) !=
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
} else { /* Discard invalid addr class (see Note #2). */
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrSrcCtr);
*perr = NET_IP_ERR_INVALID_ADDR_SRC;
return;
}
}
}
/*$PAGE*/
/* ------------- VALIDATE IP DEST ADDR ------------ */
/* See Note #1a5. */
/* Chk localhost (see Note #1a5A1). */
if ((addr_dest & NET_IP_ADDR_LOCAL_HOST_MASK) == NET_IP_ADDR_LOCAL_HOST) {
/* Chk localhost invalid addrs. */
if ((addr_dest & NET_IP_ADDR_LOCAL_HOST_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_LOCAL_HOST_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
if ((addr_dest & NET_IP_ADDR_LOCAL_HOST_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_LOCAL_HOST_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
} else {
/* Chk invalid 'This Host' (see Note #1a5B1). */
if (addr_dest == NET_IP_ADDR_THIS_HOST) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/* Chk limited broadcast (see Note #1a5B2). */
if (addr_dest != NET_IP_ADDR_BROADCAST) {
if ((addr_dest & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
/* Chk Class-A specified host (see Note #1a5B2). */
if ((addr_dest & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
} else if ((addr_dest & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
/* Chk Class-B specified host (see Note #1a5B2). */
if ((addr_dest & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
} else if ((addr_dest & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
/* Chk Class-C specified host (see Note #1a5B2). */
if ((addr_dest & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_THIS_HOST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
} else { /* Discard invalid addr class (see Note #2). */
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
/* Chk subnet specified host (see Note #1a5B2). */
if (NetIP_AddrThisHostSubnetMask != NET_IP_ADDR_NONE) {
if ((addr_dest & NetIP_AddrThisHostSubnetMask) ==
NetIP_AddrThisHostSubnetNet ) {
if ((addr_dest & NetIP_AddrThisHostSubnetMaskHost) ==
(NET_IP_ADDR_THIS_HOST & NetIP_AddrThisHostSubnetMaskHost)) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrAddrDestCtr);
*perr = NET_IP_ERR_INVALID_ADDR_DEST;
return;
}
}
}
}
}
/*$PAGE*/
/* ---------------- VALIDATE IP FLAGS ----------------- */
flag_mask = NET_IP_FLAG_NONE |
NET_IP_FLAG_TX_DONT_FRAG;
if ((flags & ~flag_mask) != NET_IP_FLAG_NONE) { /* If any invalid flags req'd, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrTxHdrFlagsCtr);
*perr = NET_IP_ERR_INVALID_FLAG;
return;
}
/* ----------------- VALIDATE IP OPTS ----------------- */
if (popts != (void *)0) {
NetIP_TxPktValidateOpt(popts, perr);
if (*perr != NET_IP_ERR_NONE) {
return;
}
}
/* -------------- IGNORE VALID IP FIELDS -------------- */
(void)&TTL; /* Prevent compiler warning. */
*perr = NET_IP_ERR_NONE;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktValidateOpt()
*
* Description : (1) Validate IP transmit option configurations :
*
* (a) IP transmit options MUST be configured by appropriate transmit options configuration
* data structure(s) passed via 'popts'; see 'net_ip.h IP HEADER OPTION CONFIGURATION
* DATA TYPES' for IP options configuration.
*
* (b) IP header allows for a maximum option size of 40 octets (see 'net_ip.h IP HEADER
* OPTIONS DEFINES Note #3').
*
*
* Argument(s) : popts Pointer to one or more IP options configuration data structures (see Note #1a) :
*
* NET_IP_OPT_CFG_ROUTE_TS IP Route &/or Internet Timestamp options configuration.
* NET_IP_OPT_CFG_SECURITY Security options configuration
* (see 'net_ip.c Note #1f').
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP transmit option configurations validated.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
* NET_IP_ERR_INVALID_OPT_LEN Total options length exceeds maximum IP
* options length (see Note #1b).
* NET_IP_ERR_INVALID_OPT_CFG Invalid number of exclusive IP options
* (see Note #3).
*
* - RETURNED BY NetIP_TxPktValidateOptRouteTS() : -
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
* NET_IP_ERR_INVALID_OPT_LEN Invalid number of Route &/or Internet
* Timestamp entries configured.
* NET_IP_ERR_INVALID_OPT_ROUTE Invalid route address(s).
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPktValidate().
*
* Note(s) : (2) (a) See 'net_ip.h IP HEADER OPTIONS DEFINES' for supported IP options' summary.
*
* (b) See 'net_ip.c Note #5' for unsupported IP options.
*
* (3) The following IP transmit options MUST be configured exclusively--i.e. only a single IP Route
* or Internet Timestamp option may be configured for any one IP datagram :
*
* (a) NET_IP_OPT_CFG_TYPE_ROUTE_STRICT
* (b) NET_IP_OPT_CFG_TYPE_ROUTE_LOOSE
* (c) NET_IP_OPT_CFG_TYPE_ROUTE_REC
* (d) NET_IP_OPT_CFG_TYPE_TS_ONLY
* (e) NET_IP_OPT_CFG_TYPE_TS_ROUTE_REC
* (f) NET_IP_OPT_CFG_TYPE_TS_ROUTE_SPEC
*
* (A) RFC #1122, Section 3.2.1.8.(c) prohibits "an IP header" from transmitting
* with "more than one Source Route option".
*
* (4) RFC #791, Section 3.1 'Options : Internet Timestamp' states that "each timestamp"
* may be "preceded with [an] internet address".
*********************************************************************************************************
*/
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetIP_TxPktValidateOpt (void *popts,
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_INT08U opt_len_size;
CPU_INT08U opt_len;
CPU_INT08U opt_nbr_route_ts;
NET_TYPE *popt_cfg_type;
void *popt_cfg;
void *popt_next;
opt_len_size = 0;
opt_nbr_route_ts = 0;
popt_cfg = popts;
while (popt_cfg != (void *)0) {
popt_cfg_type = (NET_TYPE *)popt_cfg;
switch (*popt_cfg_type) {
case NET_IP_OPT_CFG_TYPE_ROUTE_STRICT:
case NET_IP_OPT_CFG_TYPE_ROUTE_LOOSE:
case NET_IP_OPT_CFG_TYPE_ROUTE_REC:
case NET_IP_OPT_CFG_TYPE_TS_ONLY:
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_REC:
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_SPEC:
if (opt_nbr_route_ts > 0) { /* If > 1 exclusive IP opt, rtn err (see Note #3A). */
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptCfgCtr);
*perr = NET_IP_ERR_INVALID_OPT_CFG;
return;
}
opt_nbr_route_ts++;
NetIP_TxPktValidateOptRouteTS(popt_cfg, &opt_len, &popt_next, perr);
break;
#if 0 /* --------------- UNSUPPORTED IP OPTS ---------------- */
/* See Note #2b. */
case NET_IP_OPT_CFG_TYPE_SECURITY:
case NET_IP_OPT_CFG_TYPE_SECURITY_EXTENDED:
/* 'break' intentionally omitted; do NOT move from the */
/* ... following case : 'NET_IP_OPT_CFG_TYPE_NONE'. */
#endif
case NET_IP_OPT_CFG_TYPE_NONE: /* ----------------- INVALID IP OPTS ------------------ */
default:
NET_CTR_ERR_INC(NetIP_ErrTxOptTypeCtr);
*perr = NET_IP_ERR_INVALID_OPT_TYPE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
if (*perr != NET_IP_ERR_NONE) {
return;
}
opt_len_size += opt_len;
if (opt_len_size > NET_IP_HDR_OPT_SIZE_MAX) { /* If tot opt len exceeds max opt len, rtn err. */
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptLenCtr);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return;
}
popt_cfg = popt_next; /* Validate next cfg opt. */
}
*perr = NET_IP_ERR_NONE;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktValidateOptRouteTS()
*
* Description : (1) Validate IP Route &/or Internet Timestamp option configuration :
*
* (a) See 'net_ip.h IP ROUTE & INTERNET TIMESTAMP OPTIONS CONFIGURATION DATA TYPE' for
* valid IP Route &/or Internet Timestamp option configuration.
*
* (b) Packets with the following invalid options configuration will be "silently discarded" :
*
* (1) Type
* (2) Number
* * Less than minimum
* * Greater than maximum
* (3) IP Route addresses
* * MUST be IP Class A, B, or C address See 'net_ip.h IP ADDRESS DEFINES Note #2'
* (4) Internet Timestamps
* * Timestamp values are NOT validated
*
* (c) Return option values.
*
*
* Argument(s) : popt_route_ts Pointer to IP Route &/or Internet Timestamp option configuration data structure.
* ------------- Argument checked in NetIP_TxPktValidateOpt().
*
* popt_len Pointer to variable that will receive the Route/Internet Timestamp option length
* -------- (in octets).
*
* Argument validated in NetIP_TxPktValidateOpt().
*
* popt_next Pointer to variable that will receive the pointer to the next IP transmit option.
* --------- Argument validated in NetIP_TxPktValidateOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Route &/or Internet Timestamp option
* configuration validated.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
* NET_IP_ERR_INVALID_OPT_LEN Invalid number of Route &/or Internet
* Timestamp entries configured.
* NET_IP_ERR_INVALID_OPT_ROUTE Invalid route address(s).
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPktValidateOpt().
*
* Note(s) : none.
*********************************************************************************************************
*/
/*$PAGE*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetIP_TxPktValidateOptRouteTS (void *popt_route_ts,
CPU_INT08U *popt_len,
void **popt_next,
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_IP_OPT_CFG_ROUTE_TS *popt_cfg_route_ts;
CPU_INT08U opt_nbr_min;
CPU_INT08U opt_nbr_max;
CPU_INT08U opt_len;
CPU_INT08U opt_len_opt;
CPU_INT08U opt_len_param;
CPU_INT08U opt_route_ix;
CPU_BOOLEAN opt_route_spec;
NET_IP_ADDR opt_route_addr;
popt_cfg_route_ts = (NET_IP_OPT_CFG_ROUTE_TS *)popt_route_ts;
/* ------------------ VALIDATE TYPE ------------------- */
switch (popt_cfg_route_ts->Type) {
case NET_IP_OPT_CFG_TYPE_ROUTE_STRICT:
opt_nbr_min = NET_IP_OPT_PARAM_NBR_MIN;
opt_nbr_max = NET_IP_OPT_PARAM_NBR_MAX_ROUTE;
opt_len_opt = NET_IP_HDR_OPT_SIZE_ROUTE;
opt_len_param = sizeof(NET_IP_ADDR);
opt_route_spec = DEF_YES;
break;
case NET_IP_OPT_CFG_TYPE_ROUTE_LOOSE:
opt_nbr_min = NET_IP_OPT_PARAM_NBR_MIN;
opt_nbr_max = NET_IP_OPT_PARAM_NBR_MAX_ROUTE;
opt_len_opt = NET_IP_HDR_OPT_SIZE_ROUTE;
opt_len_param = sizeof(NET_IP_ADDR);
opt_route_spec = DEF_YES;
break;
case NET_IP_OPT_CFG_TYPE_ROUTE_REC:
opt_nbr_min = NET_IP_OPT_PARAM_NBR_MIN;
opt_nbr_max = NET_IP_OPT_PARAM_NBR_MAX_ROUTE;
opt_len_opt = NET_IP_HDR_OPT_SIZE_ROUTE;
opt_len_param = sizeof(NET_IP_ADDR);
opt_route_spec = DEF_NO;
break;
case NET_IP_OPT_CFG_TYPE_TS_ONLY:
opt_nbr_min = NET_IP_OPT_PARAM_NBR_MIN;
opt_nbr_max = NET_IP_OPT_PARAM_NBR_MAX_TS_ONLY;
opt_len_opt = NET_IP_HDR_OPT_SIZE_TS;
opt_len_param = sizeof(NET_TS);
opt_route_spec = DEF_NO;
break;
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_REC:
opt_nbr_min = NET_IP_OPT_PARAM_NBR_MIN;
opt_nbr_max = NET_IP_OPT_PARAM_NBR_MAX_TS_ROUTE;
opt_len_opt = NET_IP_HDR_OPT_SIZE_TS;
opt_len_param = sizeof(NET_IP_ADDR) + sizeof(NET_TS);
opt_route_spec = DEF_NO;
break;
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_SPEC:
opt_nbr_min = NET_IP_OPT_PARAM_NBR_MIN;
opt_nbr_max = NET_IP_OPT_PARAM_NBR_MAX_TS_ROUTE;
opt_len_opt = NET_IP_HDR_OPT_SIZE_TS;
opt_len_param = sizeof(NET_IP_ADDR) + sizeof(NET_TS);
opt_route_spec = DEF_YES;
break;
case NET_IP_OPT_CFG_TYPE_NONE:
default:
NET_CTR_ERR_INC(NetIP_ErrTxOptTypeCtr);
*perr = NET_IP_ERR_INVALID_OPT_TYPE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/*$PAGE*/
/* ------------------- VALIDATE NBR ------------------- */
if (popt_cfg_route_ts->Nbr < opt_nbr_min) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptLenCtr);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return;
}
if (popt_cfg_route_ts->Nbr > opt_nbr_max) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptLenCtr);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return;
}
/* ------------------ VALIDATE ROUTE ------------------ */
if (opt_route_spec == DEF_YES) { /* For specified routes ... */
/* ... validate all route addrs (see Note #1b3). */
for (opt_route_ix = 0; opt_route_ix < popt_cfg_route_ts->Nbr; opt_route_ix++) {
opt_route_addr = popt_cfg_route_ts->Route[opt_route_ix];
if ((opt_route_addr & NET_IP_ADDR_CLASS_A_MASK) != NET_IP_ADDR_CLASS_A) {
if ((opt_route_addr & NET_IP_ADDR_CLASS_B_MASK) != NET_IP_ADDR_CLASS_B) {
if ((opt_route_addr & NET_IP_ADDR_CLASS_C_MASK) != NET_IP_ADDR_CLASS_C) {
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptCfgCtr);
*perr = NET_IP_ERR_INVALID_OPT_ROUTE;
return;
}
}
}
}
}
/* ------------------- VALIDATE TS -------------------- */
/* See Note #1b4. */
/* ------------------- RTN OPT VALS ------------------- */
opt_len = opt_len_opt + (popt_cfg_route_ts->Nbr * opt_len_param);
*popt_len = opt_len;
*popt_next = popt_cfg_route_ts->NextOptPtr;
*perr = NET_IP_ERR_NONE;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPkt()
*
* Description : (1) Prepare IP header & transmit IP packet :
*
* (a) Prepare IP options (if any)
* (b) Calculate IP header buffer controls
* (c) Check for transmit fragmentation See Note #2
* (d) Prepare IP header
* (e) Transmit IP packet datagram
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit IP packet.
* ---- Argument checked in NetIP_Tx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Tx().
*
* addr_src Source IP address.
* -------- Argument checked in NetIP_TxPktValidate().
*
* addr_dest Destination IP address.
* --------- Argument checked in NetIP_TxPktValidate().
*
* TOS Specific TOS to transmit IP packet
* --- (see 'net_ip.h IP HEADER TYPE OF SERVICE (TOS) DEFINES').
* Argument checked in NetIP_TxPktValidate().
*
* TTL Specific TTL to transmit IP packet (see RFC #1122, Section 3.2.1.7) :
* ---
* NET_IP_HDR_TTL_MIN 1 minimum TTL transmit value
* NET_IP_HDR_TTL_MAX 255 maximum TTL transmit value
* NET_IP_HDR_TTL_DFLT default TTL transmit value
* NET_IP_HDR_TTL_NONE 0 replace with default TTL
*
* Argument validated in NetIP_TxPktValidate().
*
* 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.
*
* Argument checked in NetIP_TxPktValidate().
*
* 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').
*
* Argument checked in NetIP_TxPktValidate().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_INVALID_LEN_HDR Invalid IP header length.
* NET_IP_ERR_INVALID_FRAG Invalid IP fragmentation.
* NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type.
*
* --- RETURNED BY NetIP_TxPktPrepareOpt() : ----
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP option length.
*
* --- RETURNED BY NetIP_TxPktPrepareHdr() : ----
* NET_BUF_ERR_INVALID_IX Invalid/insufficient buffer index.
* NET_BUF_ERR_INVALID_LEN Invalid buffer length.
* NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer.
* NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size.
*
* ---- RETURNED BY NetIP_TxPktDatagram() : -----
* NET_IP_ERR_NONE IP datagram successfully received & processed.
* NET_IF_ERR_NONE Packet successfully transmitted.
* NET_ERR_RX Receive error; packet discarded.
* NET_ERR_TX Transmit error; packet discarded.
* NET_IP_ERR_TX_DEST_INVALID Invalid transmit destination.
* NET_IP_ERR_INVALID_ADDR_HOST Invalid IP host address.
* NET_IP_ERR_INVALID_ADDR_NET Invalid IP net address.
* NET_IP_ERR_INVALID_ADDR_GATEWAY Invalid IP gateway address.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* Return(s) : none.
*
* Caller(s) : NetIP_Tx().
*
* Note(s) : (2) IP transmit fragmentation NOT currently supported (see 'net_ip.c Note #1e').
*
* (3) Default case already invalidated in NetIP_TxPktValidate(). However, the default case
* is included as an extra precaution in case 'ProtocolHdrType' is incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_TxPkt (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
void *popts,
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
#if 0 /* #### NOT currently implemented (see Note #2). */
CPU_BOOLEAN flag_dont_frag;
#endif
CPU_INT08U ip_opt_len_size;
CPU_INT16U ip_hdr_len_size;
CPU_INT16U protocol_ix;
CPU_INT16U ip_mtu;
NET_IP_OPT_SIZE ip_hdr_opts[NET_IP_HDR_OPT_NBR_MAX];
CPU_BOOLEAN ip_tx_frag;
/* ----------------- PREPARE IP OPTS ------------------ */
if (popts != (void *)0) {
ip_opt_len_size = NetIP_TxPktPrepareOpt((void *) popts,
(CPU_INT08U *)&ip_hdr_opts[0],
(NET_ERR *) perr);
if (*perr != NET_IP_ERR_NONE) {
return;
}
} else {
ip_opt_len_size = 0;
}
/* ---------------- CALC IP HDR CTRLS ----------------- */
/* Calc tot IP hdr len (in octets). */
ip_hdr_len_size = (CPU_INT16U)(NET_IP_HDR_SIZE_MIN + ip_opt_len_size);
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (ip_hdr_len_size > NET_IP_HDR_SIZE_MAX) {
*perr = NET_IP_ERR_INVALID_LEN_HDR;
return;
}
#endif
switch (pbuf_hdr->ProtocolHdrType) {
case NET_PROTOCOL_TYPE_ICMP:
protocol_ix = pbuf_hdr->ICMP_MsgIx;
break;
case NET_PROTOCOL_TYPE_UDP:
case NET_PROTOCOL_TYPE_TCP:
protocol_ix = pbuf_hdr->TCP_UDP_HdrDataIx;
break;
case NET_PROTOCOL_TYPE_NONE:
default: /* See Note #3. */
NET_CTR_ERR_INC(NetIP_ErrTxProtocolCtr);
*perr = NET_ERR_INVALID_PROTOCOL;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/*$PAGE*/
/* ----------------- CHK FRAG REQUIRED ---------------- */
ip_tx_frag = DEF_NO;
if (protocol_ix < ip_hdr_len_size) { /* If hdr len > allowed rem ix, tx frag req'd. */
ip_tx_frag = DEF_YES;
}
ip_mtu = NET_IF_MTU - ip_hdr_len_size;
if (pbuf_hdr->TotLen > ip_mtu) { /* If tot len > MTU, tx frag req'd. */
ip_tx_frag = DEF_YES;
}
if (ip_tx_frag == DEF_NO) { /* If tx frag NOT required, ... */
NetIP_TxPktPrepareHdr(pbuf, /* ... prepare IP hdr ... */
pbuf_hdr,
ip_hdr_len_size,
ip_opt_len_size,
protocol_ix,
addr_src,
addr_dest,
TOS,
TTL,
flags,
&ip_hdr_opts[0],
perr);
if (*perr != NET_IP_ERR_NONE) {
return;
}
NetIP_TxPktDatagram(pbuf, pbuf_hdr, perr); /* ... & tx IP datagram. */
} else {
#if 0 /* #### NOT currently implemented (see Note #2). */
flag_dont_frag = DEF_BIT_IS_SET(flags, NET_IP_FLAG_TX_DONT_FRAG);
if (flag_dont_frag != DEF_NO) {
*perr = NET_IP_ERR_INVALID_FRAG;
return;
}
#else
*perr = NET_IP_ERR_INVALID_FRAG;
return;
#endif
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktPrepareOpt()
*
* Description : (1) Prepare IP header with IP transmit options :
*
* (a) Prepare ALL IP options from configuration
* data structure(s)
* (b) Pad remaining IP header octets See RFC #791, Section 3.1 'Padding'
*
* (2) IP transmit options MUST be configured by appropriate options configuration data structure(s)
* passed via 'popts'; see 'net_ip.h IP HEADER OPTION CONFIGURATION DATA TYPES' for IP options
* configuration.
*
* (3) Convert ALL IP options' multi-octet words from host-order to network-order.
*
*
* Argument(s) : popts Pointer to one or more IP options configuration data structures (see Note #2) :
* -----
* 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').
*
* Argument checked in NetIP_TxPkt().
*
* popt_hdr Pointer to IP transmit option buffer to prepare IP options.
* -------- Argument validated in NetIP_TxPkt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP header options successfully prepared.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
* NET_IP_ERR_INVALID_OPT_LEN Invalid IP option length.
*
* Return(s) : Total IP option length (in octets), if NO errors.
*
* 0, otherwise.
*
* Caller(s) : NetIP_TxPkt().
*
* Note(s) : (4) Transmit arguments & options validated in NetIP_TxPktValidate()/NetIP_TxPktValidateOpt() :
*
* (a) Assumes ALL transmit arguments & options are valid
* (b) Assumes total transmit options' lengths are valid
*
* (5) IP header allows for a maximum option size of 40 octets (see 'net_ip.h IP HEADER OPTIONS
* DEFINES Note #3').
*
* (6) Default case already invalidated in NetIP_TxPktValidateOpt(). However, the default
* case is included as an extra precaution in case any of the IP transmit options types
* are incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static CPU_INT08U NetIP_TxPktPrepareOpt (void *popts,
CPU_INT08U *popt_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_INT08U ip_opt_len_tot;
CPU_INT08U ip_opt_len;
CPU_INT08U *popt_cfg_hdr;
NET_TYPE *popt_cfg_type;
void *popt_next;
void *popt_cfg;
ip_opt_len_tot = 0;
popt_cfg = popts;
popt_cfg_hdr = popt_hdr;
/* ----------------- PREPARE IP OPTS ------------------ */
while (popt_cfg != (void *)0) { /* Prepare ALL cfg'd IP opts (see Note #1a). */
popt_cfg_type = (NET_TYPE *)popt_cfg;
switch (*popt_cfg_type) {
case NET_IP_OPT_CFG_TYPE_ROUTE_STRICT:
case NET_IP_OPT_CFG_TYPE_ROUTE_LOOSE:
case NET_IP_OPT_CFG_TYPE_ROUTE_REC:
NetIP_TxPktPrepareOptRoute(popt_cfg, popt_cfg_hdr, &ip_opt_len, &popt_next, perr);
break;
case NET_IP_OPT_CFG_TYPE_TS_ONLY:
NetIP_TxPktPrepareOptTS(popt_cfg, popt_cfg_hdr, &ip_opt_len, &popt_next, perr);
break;
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_REC:
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_SPEC:
NetIP_TxPktPrepareOptTSRoute(popt_cfg, popt_cfg_hdr, &ip_opt_len, &popt_next, perr);
break;
#if 0 /* --------------- UNSUPPORTED IP OPTS ---------------- */
case NET_IP_OPT_CFG_TYPE_SECURITY:
case NET_IP_OPT_CFG_TYPE_SECURITY_EXTENDED:
break;
#endif
/* ----------------- INVALID IP OPTS ------------------ */
case NET_IP_OPT_CFG_TYPE_NONE:
default: /* See Note #6. */
NET_CTR_ERR_INC(NetIP_ErrTxOptTypeCtr);
*perr = NET_IP_ERR_INVALID_OPT_TYPE;
return (0); /* Prevent 'break NOT reachable' compiler warning. */
}
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (*perr != NET_IP_ERR_NONE) { /* See Note #4a. */
return (0);
}
if (ip_opt_len_tot > NET_IP_HDR_OPT_SIZE_MAX) { /* See Note #4b. */
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptLenCtr);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (0);
}
#endif
ip_opt_len_tot += ip_opt_len;
popt_cfg_hdr += ip_opt_len;
popt_cfg = popt_next; /* Prepare next cfg opt. */
}
/*$PAGE*/
/* -------------------- PAD IP HDR -------------------- */
if (ip_opt_len_tot > 0) {
/* Pad rem'ing IP hdr octets (see Note #1b). */
while ((ip_opt_len_tot % NET_IP_HDR_OPT_SIZE_WORD) &&
(ip_opt_len_tot <= NET_IP_HDR_OPT_SIZE_MAX )) {
*popt_cfg_hdr = NET_IP_HDR_OPT_PAD;
popt_cfg_hdr++;
ip_opt_len_tot++;
}
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (ip_opt_len_tot > NET_IP_HDR_OPT_SIZE_MAX) { /* See Note #4b. */
NET_CTR_ERR_INC(NetIP_ErrTxHdrOptLenCtr);
*perr = NET_IP_ERR_INVALID_OPT_LEN;
return (0);
}
#endif
}
*perr = NET_IP_ERR_NONE;
return (ip_opt_len_tot);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktPrepareOptRoute()
*
* Description : (1) Prepare IP header with IP Route transmit options :
*
* (a) Prepare IP Route option header
* (b) Prepare IP Route
*
* (2) See RFC #791, Section 3.1 'Options : Loose/Strict Source & Record Route'.
*
*
* Argument(s) : popts Pointer to IP Route option configuration data structure.
* ----- Argument checked in NetIP_TxPktPrepareOpt().
*
* popt_hdr Pointer to IP transmit option buffer to prepare IP Route option.
* -------- Argument validated in NetIP_TxPkt().
*
* popt_len Pointer to variable that will receive the Route option length (in octets).
* -------- Argument validated in NetIP_TxPktPrepareOpt().
*
* popt_next Pointer to variable that will receive the pointer to the next IP transmit option.
* -------- Argument validated in NetIP_TxPktPrepareOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP Route option successfully prepared.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPktPrepareOpt().
*
* Note(s) : (3) Transmit arguments & options validated in NetIP_TxPktValidate()/NetIP_TxPktValidateOpt() :
*
* (a) Assumes ALL transmit arguments & options are valid
* (b) Assumes total transmit options' lengths are valid
*
* (4) Default case already invalidated in NetIP_TxPktValidateOpt(). However, the default
* case is included as an extra precaution in case any of the IP transmit options types
* are incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_TxPktPrepareOptRoute (void *popts,
CPU_INT08U *popt_hdr,
CPU_INT08U *popt_len,
void **popt_next,
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_IP_OPT_CFG_ROUTE_TS *popt_cfg_route_ts;
NET_IP_OPT_SRC_ROUTE *popt_route;
CPU_BOOLEAN opt_route_spec;
CPU_INT08U opt_route_ix;
NET_IP_ADDR opt_route_addr;
/* -------------- PREPARE ROUTE OPT HDR --------------- */
popt_cfg_route_ts = (NET_IP_OPT_CFG_ROUTE_TS *)popts;
popt_route = (NET_IP_OPT_SRC_ROUTE *)popt_hdr;
popt_route->Len = NET_IP_HDR_OPT_SIZE_ROUTE + (popt_cfg_route_ts->Nbr * sizeof(NET_IP_ADDR));
popt_route->Ptr = NET_IP_OPT_ROUTE_PTR_ROUTE;
popt_route->Pad = NET_IP_HDR_OPT_PAD; /* ???? PAD &/or NOP val? */
switch (popt_cfg_route_ts->Type) {
case NET_IP_OPT_CFG_TYPE_ROUTE_STRICT:
popt_route->Type = NET_IP_HDR_OPT_ROUTE_SRC_STRICT;
opt_route_spec = DEF_YES;
break;
case NET_IP_OPT_CFG_TYPE_ROUTE_LOOSE:
popt_route->Type = NET_IP_HDR_OPT_ROUTE_SRC_LOOSE;
opt_route_spec = DEF_YES;
break;
case NET_IP_OPT_CFG_TYPE_ROUTE_REC:
popt_route->Type = NET_IP_HDR_OPT_ROUTE_REC;
opt_route_spec = DEF_NO;
break;
case NET_IP_OPT_CFG_TYPE_NONE:
default: /* See Note #4. */
NET_CTR_ERR_INC(NetIP_ErrTxOptTypeCtr);
*perr = NET_IP_ERR_INVALID_OPT_TYPE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ------------------ PREPARE ROUTE ------------------- */
for (opt_route_ix = 0; opt_route_ix < popt_cfg_route_ts->Nbr; opt_route_ix++) {
/* Cfg specified or rec route addrs. */
if (opt_route_spec == DEF_YES) {
opt_route_addr = popt_cfg_route_ts->Route[opt_route_ix];
} else {
opt_route_addr = (NET_IP_ADDR)NET_IP_ADDR_NONE;
}
NET_UTIL_VAL_COPY_SET_NET_32(&popt_route->Route[opt_route_ix], &opt_route_addr);
}
*popt_len = popt_route->Len;
*popt_next = popt_cfg_route_ts->NextOptPtr;
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktPrepareOptTS()
*
* Description : (1) Prepare IP header with Internet Timestamp option :
*
* (a) Prepare Internet Timestamp option header
* (b) Prepare Internet Timestamps
*
* (2) See RFC #791, Section 3.1 'Options : Internet Timestamp'.
*
*
* Argument(s) : popts Pointer to Internet Timestamp option configuration data structure.
* ----- Argument checked in NetIP_TxPktPrepareOpt().
*
* popt_hdr Pointer to IP transmit option buffer to prepare Internet Timestamp option.
* -------- Argument validated in NetIP_TxPkt().
*
* popt_len Pointer to variable that will receive the Internet Timestamp option length
* -------- (in octets).
*
* Argument validated in NetIP_TxPktPrepareOpt().
*
* popt_next Pointer to variable that will receive the pointer to the next IP transmit option.
* -------- Argument validated in NetIP_TxPktPrepareOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Internet Timestamp option successfully prepared.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPktPrepareOpt().
*
* Note(s) : (3) Transmit arguments & options validated in NetIP_TxPktValidate()/NetIP_TxPktValidateOpt() :
*
* (a) Assumes ALL transmit arguments & options are valid
* (b) Assumes total transmit options' lengths are valid
*
* (4) Default case already invalidated in NetIP_TxPktValidateOpt(). However, the default
* case is included as an extra precaution in case any of the IP transmit options types
* are incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_TxPktPrepareOptTS (void *popts,
CPU_INT08U *popt_hdr,
CPU_INT08U *popt_len,
void **popt_next,
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_IP_OPT_CFG_ROUTE_TS *popt_cfg_route_ts;
NET_IP_OPT_TS *popt_ts;
CPU_INT08U opt_ts_ovf;
CPU_INT08U opt_ts_flags;
CPU_INT08U opt_ts_ix;
NET_TS opt_ts;
/* ---------------- PREPARE TS OPT HDR ---------------- */
popt_cfg_route_ts = (NET_IP_OPT_CFG_ROUTE_TS *)popts;
switch (popt_cfg_route_ts->Type) {
case NET_IP_OPT_CFG_TYPE_TS_ONLY:
popt_ts = (NET_IP_OPT_TS *)popt_hdr;
popt_ts->Type = NET_IP_HDR_OPT_TS;
popt_ts->Len = NET_IP_HDR_OPT_SIZE_TS + (popt_cfg_route_ts->Nbr * sizeof(NET_TS));
popt_ts->Ptr = NET_IP_OPT_TS_PTR_TS;
opt_ts_ovf = 0;
opt_ts_flags = NET_IP_OPT_TS_FLAG_TS_ONLY;
popt_ts->Ovf_Flags = opt_ts_ovf | opt_ts_flags;
break;
case NET_IP_OPT_CFG_TYPE_NONE:
default: /* See Note #4. */
NET_CTR_ERR_INC(NetIP_ErrTxOptTypeCtr);
*perr = NET_IP_ERR_INVALID_OPT_TYPE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* -------------------- PREPARE TS -------------------- */
for (opt_ts_ix = 0; opt_ts_ix < popt_cfg_route_ts->Nbr; opt_ts_ix++) {
opt_ts = popt_cfg_route_ts->TS[opt_ts_ix];
NET_UTIL_VAL_COPY_SET_NET_32(&popt_ts->TS[opt_ts_ix], &opt_ts);
}
*popt_len = popt_ts->Len;
*popt_next = popt_cfg_route_ts->NextOptPtr;
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktPrepareOptTSRoute()
*
* Description : (1) Prepare IP header with Internet Timestamp with IP Route option :
*
* (a) Prepare Internet Timestamp option header
* (b) Prepare Internet Timestamps
*
* (2) See RFC #791, Section 3.1 'Options : Internet Timestamp'.
*
*
* Argument(s) : popts Pointer to Internet Timestamp option configuration data structure.
* ----- Argument checked in NetIP_TxPktPrepareOpt().
*
* popt_hdr Pointer to IP transmit option buffer to prepare Internet Timestamp option.
* -------- Argument validated in NetIP_TxPkt().
*
* popt_len Pointer to variable that will receive the Internet Timestamp option length
* -------- Argument validated in NetIP_TxPktPrepareOpt().
* (in octets).
*
* popt_next Pointer to variable that will receive the pointer to the next IP transmit option.
* -------- Argument validated in NetIP_TxPktPrepareOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE Internet Timestamp with IP Route option
* successfully prepared.
* NET_IP_ERR_INVALID_OPT_TYPE Invalid IP option type.
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPktPrepareOpt().
*
* Note(s) : (3) Transmit arguments & options validated in NetIP_TxPktValidate()/NetIP_TxPktValidateOpt() :
*
* (a) Assumes ALL transmit arguments & options are valid
* (b) Assumes total transmit options' lengths are valid
*
* (4) Default case already invalidated in NetIP_TxPktValidateOpt(). However, the default
* case is included as an extra precaution in case any of the IP transmit options types
* are incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_TxPktPrepareOptTSRoute (void *popts,
CPU_INT08U *popt_hdr,
CPU_INT08U *popt_len,
void **popt_next,
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_IP_OPT_CFG_ROUTE_TS *popt_cfg_route_ts;
NET_IP_OPT_TS_ROUTE *popt_ts_route;
NET_IP_ROUTE_TS *proute_ts;
CPU_INT08U opt_ts_ovf;
CPU_INT08U opt_ts_flags;
CPU_INT08U opt_ts_ix;
NET_TS opt_ts;
CPU_BOOLEAN opt_route_spec;
NET_IP_ADDR opt_route_addr;
/* ---------------- PREPARE TS OPT HDR ---------------- */
popt_cfg_route_ts = (NET_IP_OPT_CFG_ROUTE_TS *)popts;
popt_ts_route = (NET_IP_OPT_TS_ROUTE *)popt_hdr;
popt_ts_route->Type = NET_IP_HDR_OPT_TS;
popt_ts_route->Len = NET_IP_HDR_OPT_SIZE_TS + (popt_cfg_route_ts->Nbr * (sizeof(NET_IP_ADDR) + sizeof(NET_TS)));
popt_ts_route->Ptr = NET_IP_OPT_TS_PTR_TS;
opt_ts_ovf = 0;
switch (popt_cfg_route_ts->Type) {
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_REC:
opt_ts_flags = NET_IP_OPT_TS_FLAG_TS_ROUTE_REC;
popt_ts_route->Ovf_Flags = opt_ts_ovf | opt_ts_flags;
opt_route_spec = DEF_NO;
break;
case NET_IP_OPT_CFG_TYPE_TS_ROUTE_SPEC:
opt_ts_flags = NET_IP_OPT_TS_FLAG_TS_ROUTE_SPEC;
popt_ts_route->Ovf_Flags = opt_ts_ovf | opt_ts_flags;
opt_route_spec = DEF_YES;
break;
case NET_IP_OPT_CFG_TYPE_NONE:
default: /* See Note #4. */
NET_CTR_ERR_INC(NetIP_ErrTxOptTypeCtr);
*perr = NET_IP_ERR_INVALID_OPT_TYPE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ----------------- PREPARE ROUTE/TS ----------------- */
proute_ts = &popt_ts_route->Route_TS[0];
for (opt_ts_ix = 0; opt_ts_ix < popt_cfg_route_ts->Nbr; opt_ts_ix++) {
/* Cfg specified or rec route addrs. */
if (opt_route_spec == DEF_YES) {
opt_route_addr = popt_cfg_route_ts->Route[opt_ts_ix];
} else {
opt_route_addr = (NET_IP_ADDR)NET_IP_ADDR_NONE;
}
NET_UTIL_VAL_COPY_SET_NET_32(&proute_ts->Route[opt_ts_ix], &opt_route_addr);
opt_ts = popt_cfg_route_ts->TS[opt_ts_ix];
NET_UTIL_VAL_COPY_SET_NET_32(&proute_ts->TS[opt_ts_ix], &opt_ts);
}
*popt_len = popt_ts_route->Len;
*popt_next = popt_cfg_route_ts->NextOptPtr;
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktPrepareHdr()
*
* Description : (1) Prepare IP header :
*
* (a) Update network buffer's protocol index & length controls.
*
* (b) Prepare the transmit packet's following IP header fields :
*
* (1) Version
* (2) Header Length
* (3) Type of Service (TOS)
* (4) Total Length
* (5) Identification (ID)
* (6) Flags
* (7) Fragment Offset
* (8) Time-to-Live (TTL)
* (9) Protocol
* (10) Check-Sum See Note #6
* (11) Source Address
* (12) Destination Address
* (13) Options
*
* (c) Convert the following IP header fields from host-order to network-order :
*
* (1) Total Length
* (2) Identification (ID)
* (3) Flags/Fragment Offset
* (4) Source Address
* (5) Destination Address
* (6) Check-Sum See Note #6c
* (7) Options See Note #5
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit IP packet.
* ---- Argument checked in NetIP_Tx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Tx().
*
* ip_hdr_len_tot Total IP header length.
* -------------- Argument checked in NetIP_TxPkt().
*
* ip_opt_len_tot Total IP header options' length.
* -------------- Argument checked in NetIP_TxPktPrepareOpt().
*
* protocol_ix Index to higher-layer protocol header.
*
* addr_src Source IP address.
* -------- Argument checked in NetIP_TxPktValidate().
*
* addr_dest Destination IP address.
* --------- Argument checked in NetIP_TxPktValidate().
*
* TOS Specific TOS to transmit IP packet
* --- (see 'net_ip.h IP HEADER TYPE OF SERVICE (TOS) DEFINES').
* Argument checked in NetIP_TxPktValidate().
*
* TTL Specific TTL to transmit IP packet (see RFC #1122, Section 3.2.1.7) :
* ---
* NET_IP_HDR_TTL_MIN 1 minimum TTL transmit value
* NET_IP_HDR_TTL_MAX 255 maximum TTL transmit value
* NET_IP_HDR_TTL_DFLT default TTL transmit value
* NET_IP_HDR_TTL_NONE 0 replace with default TTL
*
* Argument validated in NetIP_TxPktValidate().
*
* 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.
*
* Argument checked in NetIP_TxPktValidate().
*
* pip_hdr_opts Pointer to IP options buffer.
* ------------ Argument checked in NetIP_TxPktPrepareOpt().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP header successfully prepared.
* NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type.
*
* ----------- RETURNED BY NetBuf_DataWr() : -----------
* NET_BUF_ERR_INVALID_IX Invalid buffer index for transmit options.
* NET_BUF_ERR_INVALID_LEN Invalid buffer length for transmit options.
*
* - RETURNED BY NetUtil_16BitOnesCplChkSumHdrCalc() : -
* NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer.
* NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size.
*
*$PAGE*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPkt().
*
* Note(s) : (2) See 'net_ip.h IP HEADER' for IP header format.
*
* (3) Supports ONLY the following protocols :
*
* (a) ICMP
* (b) UDP
* (c) TCP
*
* See also 'net.h Note #1a'.
*
* (4) Default case already invalidated in NetIP_TxPktValidate(). However, the default case is
* included as an extra precaution in case 'ProtocolHdrType' is incorrectly modified.
*
* (5) Assumes ALL IP options' multi-octet words previously converted from host-order to
* network-order.
*
* (6) (a) IP header Check-Sum MUST be calculated AFTER the entire IP header 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) IP header Check-Sum field MUST be cleared to '0' BEFORE the IP header Check-Sum is
* calculated (see RFC #791, Section 3.1 'Header Checksum').
*
* (c) The IP header 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').
*********************************************************************************************************
*/
static void NetIP_TxPktPrepareHdr (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT16U ip_hdr_len_tot,
CPU_INT08U ip_opt_len_tot,
CPU_INT16U protocol_ix,
NET_IP_ADDR addr_src,
NET_IP_ADDR addr_dest,
NET_IP_TOS TOS,
NET_IP_TTL TTL,
CPU_INT16U flags,
CPU_INT32U *pip_hdr_opts,
NET_ERR *perr)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_IP_HDR *pip_hdr;
CPU_INT08U ip_ver;
CPU_INT08U ip_hdr_len;
CPU_INT16U ip_id;
CPU_INT16U ip_flags;
CPU_INT16U ip_frag_offset;
CPU_INT16U ip_opt_ix;
CPU_INT16U ip_flags_frag_offset;
CPU_INT16U ip_chk_sum;
/* ----------------- UPDATE BUF CTRLS ----------------- */
pbuf_hdr->IP_HdrLen = ip_hdr_len_tot;
pbuf_hdr->IP_HdrIx = protocol_ix - pbuf_hdr->IP_HdrLen;
pbuf_hdr->IP_DataLen = (CPU_INT16U ) pbuf_hdr->TotLen;
pbuf_hdr->IP_DatagramLen = (CPU_INT16U ) pbuf_hdr->TotLen;
pbuf_hdr->TotLen += (NET_BUF_SIZE) pbuf_hdr->IP_HdrLen;
pbuf_hdr->IP_TotLen = (CPU_INT16U ) pbuf_hdr->TotLen;
/* ------------------ PREPARE IP HDR ------------------ */
pip_hdr = (NET_IP_HDR *)&pbuf->Data[pbuf_hdr->IP_HdrIx];
/* -------------- PREPARE IP VER/HDR LEN -------------- */
ip_ver = NET_IP_HDR_VER;
ip_ver <<= NET_IP_HDR_VER_SHIFT;
ip_hdr_len = pbuf_hdr->IP_HdrLen / NET_IP_HDR_LEN_WORD_SIZE;
ip_hdr_len &= NET_IP_HDR_LEN_MASK;
pip_hdr->Ver_HdrLen = ip_ver | ip_hdr_len;
/*$PAGE*/
/* ------------------ PREPARE IP TOS ------------------ */
pip_hdr->TOS = TOS;
/* ---------------- PREPARE IP TOT LEN ---------------- */
NET_UTIL_VAL_COPY_SET_NET_16(&pip_hdr->TotLen, &pbuf_hdr->TotLen);
/* ------------------ PREPARE IP ID ------------------- */
NET_IP_TX_GET_ID(ip_id);
NET_UTIL_VAL_COPY_SET_NET_16(&pip_hdr->ID, &ip_id);
/* --------------- PREPARE IP FLAGS/FRAG -------------- */
ip_flags = NET_IP_HDR_FLAG_NONE;
ip_flags |= flags;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
ip_flags &= NET_IP_HDR_FLAG_MASK;
#endif
ip_frag_offset = NET_IP_HDR_FRAG_OFFSET_NONE;
ip_flags_frag_offset = ip_flags | ip_frag_offset;
NET_UTIL_VAL_COPY_SET_NET_16(&pip_hdr->Flags_FragOffset, &ip_flags_frag_offset);
/* ------------------ PREPARE IP TTL ------------------ */
if (TTL != NET_IP_HDR_TTL_NONE) {
pip_hdr->TTL = TTL;
} else {
pip_hdr->TTL = NET_IP_HDR_TTL_DFLT;
}
/* --------------- PREPARE IP PROTOCOL ---------------- */
switch (pbuf_hdr->ProtocolHdrType) { /* Demux IP protocol (see Note #3). */
case NET_PROTOCOL_TYPE_ICMP:
pip_hdr->Protocol = NET_IP_HDR_PROTOCOL_ICMP;
break;
case NET_PROTOCOL_TYPE_UDP:
pip_hdr->Protocol = NET_IP_HDR_PROTOCOL_UDP;
break;
case NET_PROTOCOL_TYPE_TCP:
pip_hdr->Protocol = NET_IP_HDR_PROTOCOL_TCP;
break;
case NET_PROTOCOL_TYPE_NONE:
default: /* See Note #4. */
NET_CTR_ERR_INC(NetIP_ErrTxProtocolCtr);
*perr = NET_ERR_INVALID_PROTOCOL;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_IP; /* Update buf protocol for IP. */
/* ----------------- PREPARE IP ADDRS ----------------- */
pbuf_hdr->IP_AddrSrc = addr_src;
pbuf_hdr->IP_AddrDest = addr_dest;
NET_UTIL_VAL_COPY_SET_NET_32(&pip_hdr->AddrSrc, &addr_src);
NET_UTIL_VAL_COPY_SET_NET_32(&pip_hdr->AddrDest, &addr_dest);
/*$PAGE*/
/* ----------------- PREPARE IP OPTS ------------------ */
if (ip_opt_len_tot > 0) {
ip_opt_ix = pbuf_hdr->IP_HdrIx + NET_IP_HDR_OPT_IX;
NetBuf_DataWr((NET_BUF *)pbuf, /* See Note #5. */
(NET_BUF_SIZE)ip_opt_ix,
(NET_BUF_SIZE)ip_opt_len_tot,
(CPU_INT08U *)pip_hdr_opts,
(NET_ERR *)perr);
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (*perr != NET_BUF_ERR_NONE) {
return;
}
#endif
}
/* ---------------- PREPARE IP CHK SUM ---------------- */
/* See Note #6. */
NET_UTIL_VAL_SET_NET_16(&pip_hdr->ChkSum, 0x0000); /* Clr chk sum (see Note #6b). */
/* Calc chk sum. */
ip_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *)pip_hdr,
(CPU_INT16U)ip_hdr_len_tot,
(NET_ERR *)perr);
if (*perr != NET_UTIL_ERR_NONE) {
return;
}
NET_UTIL_VAL_COPY_16(&pip_hdr->ChkSum, &ip_chk_sum); /* Copy chk sum in net order (see Note #6c). */
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktDatagram()
*
* Description : (1) Transmit IP packet datagram :
*
* (a) Select next-hop IP address
* (b) Post IP packet datagram to next queue :
*
* (1) Destination is this host Reflect back to IP Receive
* (A) This host's address
* (B) Localhost address
* (2) Limited Broadcast Send to Network Interface Transmit
* ???? Reflect back to IP Receive
* (3) Local Host Send to Network Interface Transmit
* (4) Remote Host Send to Network Interface Transmit
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit IP packet.
* ---- Argument checked in NetIP_Tx(),
* NetIP_ReTx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Tx(),
* NetIP_ReTx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* ----------- RETURNED BY NetIP_Rx() : ------------
* NET_IP_ERR_NONE IP datagram successfully received & processed.
*
* ----------- RETURNED BY NetIF_Tx() : ------------
* NET_IF_ERR_NONE Packet successfully transmitted.
*
* - RETURNED BY NetIP_TxPktDatagramNextHopSel() : -
* NET_IP_ERR_TX_DEST_INVALID Invalid transmit destination.
* NET_IP_ERR_INVALID_ADDR_HOST Invalid IP host address.
* NET_IP_ERR_INVALID_ADDR_NET Invalid IP net address.
* NET_IP_ERR_INVALID_ADDR_GATEWAY Invalid IP gateway address.
*
*
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
* NET_ERR_TX Transmit error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPkt(),
* NetIP_ReTxPkt().
*
* Note(s) : (2) Since ALL fields in the transmit datagram's IP header have been converted from host-order
* to network-order, 'addr_dest' is passed to avoid re-conversion back to host-order.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_TxPktDatagram (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr)
{
/* ---------------- SEL NEXT-HOP ADDR ----------------- */
NetIP_TxPktDatagramNextHopSel(pbuf_hdr, perr);
switch (*perr) { /* --------------- POST IP PKT DATAGRAM --------------- */
case NET_IP_ERR_TX_DEST_THIS_HOST:
case NET_IP_ERR_TX_DEST_LOCALHOST:
/* Cfg valid rx len ctrls. */
pbuf_hdr->IF_DataLenMin = (CPU_INT16U )0;
pbuf_hdr->DataLen = (NET_BUF_SIZE)pbuf_hdr->IP_TotLen;
NetIP_Rx(pbuf, perr);
break;
case NET_IP_ERR_TX_DEST_BROADCAST:
NetIF_Tx(pbuf, perr);
#if 0 /* #### NOT yet implemented (see Note #1b2). */
/* Cfg valid rx len ctrls. */
pbuf_hdr->IF_DataLenMin = (CPU_INT16U )0;
pbuf_hdr->DataLen = (NET_BUF_SIZE)pbuf_hdr->IP_TotLen;
pbuf_hdr->RefCtr++;
NetIP_Rx(pbuf, perr);
#endif
break;
case NET_IP_ERR_TX_DEST_HOST_THIS_NET:
case NET_IP_ERR_TX_DEST_DFLT_GATEWAY:
NetIF_Tx(pbuf, perr);
break;
case NET_IP_ERR_TX_DEST_INVALID:
case NET_IP_ERR_INVALID_ADDR_HOST:
case NET_IP_ERR_INVALID_ADDR_NET:
case NET_IP_ERR_INVALID_ADDR_GATEWAY:
default:
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_TxPktDatagramNextHopSel()
*
* Description : (1) Select next-hop address for transmit IP packet datagram (see RFC #1122, Section 3.3.1) :
*
* (a) Destination is this host :
* (1) This host's address See 'net_ip.c Note #1a'
* (2) Localhost address See RFC #1122, Section 3.2.1.3.(g)
* (b) Limited Broadcast See RFC #1122, Section 3.3.1.1
* 'Special Case : Limited Broadcast'
* (c) Local Broadcast See RFC #1122, Section 3.3.1.1
* 'Special Case : Limited Broadcast'
* (d) Local Host See RFC #1122, Section 3.3.1.1.(b)
* (e) Remote Host See RFC #1122, Section 3.3.1.1.(c)
*
* (1) Destinations located on remote networks are sent directly to this host's
* default gateway (see 'net_ip.c Note #1c').
*
* (2) Configure next-hop address in network-order.
*
*
* Argument(s) : pbuf_hdr Pointer to network buffer header of IP transmit packet.
* -------- Argument validated in NetIP_Tx(),
* NetIP_ReTx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_TX_DEST_THIS_HOST Destination is this host's IP address.
* NET_IP_ERR_TX_DEST_LOCALHOST Destination is localhost.
* NET_IP_ERR_TX_DEST_BROADCAST Limited broadcast on local network.
* NET_IP_ERR_TX_DEST_HOST_THIS_NET Destination host on local network.
* NET_IP_ERR_TX_DEST_DFLT_GATEWAY Destination host on remote network.
* NET_IP_ERR_TX_DEST_INVALID Invalid IP destination address.
*
* NET_IP_ERR_INVALID_ADDR_HOST Invalid IP host address.
* NET_IP_ERR_INVALID_ADDR_NET Invalid IP net address.
* NET_IP_ERR_INVALID_ADDR_GATEWAY Invalid IP gateway address.
*
* Return(s) : none.
*
* Caller(s) : NetIP_TxPktDatagram().
*
* Note(s) : (3) See 'net_ip.h IP ADDRESS DEFINES Notes #2, #3, & #4' for supported IP addresses.
*********************************************************************************************************
*/
static void NetIP_TxPktDatagramNextHopSel (NET_BUF_HDR *pbuf_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
NET_IP_ADDR addr_dest;
/* -------------- GET IP PKT'S DEST ADDR -------------- */
addr_dest = pbuf_hdr->IP_AddrDest;
/*$PAGE*/
/* --------------- CHK THIS HOST'S ADDR --------------- */
if (addr_dest == NetIP_AddrThisHost) {
if (NetIP_AddrThisHost != NET_IP_ADDR_NONE) { /* If valid host addr cfg'd, tx via host's addr. */
pbuf_hdr->IP_AddrNextHop = (CPU_INT32U)addr_dest;
*perr = NET_IP_ERR_TX_DEST_THIS_HOST;
} else {
*perr = NET_IP_ERR_INVALID_ADDR_HOST;
return;
}
/* ---------------- CHK LOCALHOST ADDR ---------------- */
} else if ((addr_dest & NET_IP_ADDR_LOCAL_HOST_MASK) == NET_IP_ADDR_LOCAL_HOST) {
NET_CTR_STAT_INC(NetIP_StatTxDestLocalCtr);
pbuf_hdr->IP_AddrNextHop = (CPU_INT32U)addr_dest;
*perr = NET_IP_ERR_TX_DEST_LOCALHOST;
/* --------------- CHK LIMITED BROADCAST -------------- */
} else if (addr_dest == NET_IP_ADDR_BROADCAST) {
NET_CTR_STAT_INC(NetIP_StatTxDestBroadcastCtr);
DEF_BIT_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_TX);
pbuf_hdr->IP_AddrNextHop = (CPU_INT32U)addr_dest;
*perr = NET_IP_ERR_TX_DEST_BROADCAST;
/* ------------------ CHK LOCAL NET ------------------- */
} else if ((addr_dest & NetIP_AddrThisHostSubnetMask) == NetIP_AddrThisHostSubnetNet) {
/* If valid subnet cfg'd, tx via subnet. */
if ((NetIP_AddrThisHostSubnetMask != NET_IP_ADDR_NONE) &&
(NetIP_AddrThisHostSubnetNet != NET_IP_ADDR_NONE)) {
/* Chk local subnet broadcast (see #1c). */
if ((addr_dest & NetIP_AddrThisHostSubnetMaskHost) ==
(NET_IP_ADDR_BROADCAST & NetIP_AddrThisHostSubnetMaskHost)) {
NET_CTR_STAT_INC(NetIP_StatTxDestBroadcastCtr);
DEF_BIT_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_TX);
pbuf_hdr->IP_AddrNextHop = (CPU_INT32U)addr_dest;
*perr = NET_IP_ERR_TX_DEST_BROADCAST;
} else {
pbuf_hdr->IP_AddrNextHop = (CPU_INT32U)addr_dest;
*perr = NET_IP_ERR_TX_DEST_HOST_THIS_NET;
}
} else {
*perr = NET_IP_ERR_INVALID_ADDR_NET;
return;
}
/* ------------------ TX REMOTE NET ------------------- */
} else {
if ((addr_dest & NET_IP_ADDR_CLASS_A_MASK) == NET_IP_ADDR_CLASS_A) {
if ((addr_dest & NET_IP_ADDR_CLASS_A_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_A_MASK_HOST)) {
NET_CTR_STAT_INC(NetIP_StatTxDestBroadcastCtr);
}
} else if ((addr_dest & NET_IP_ADDR_CLASS_B_MASK) == NET_IP_ADDR_CLASS_B) {
if ((addr_dest & NET_IP_ADDR_CLASS_B_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_B_MASK_HOST)) {
NET_CTR_STAT_INC(NetIP_StatTxDestBroadcastCtr);
}
} else if ((addr_dest & NET_IP_ADDR_CLASS_C_MASK) == NET_IP_ADDR_CLASS_C) {
if ((addr_dest & NET_IP_ADDR_CLASS_C_MASK_HOST) ==
(NET_IP_ADDR_BROADCAST & NET_IP_ADDR_CLASS_C_MASK_HOST)) {
NET_CTR_STAT_INC(NetIP_StatTxDestBroadcastCtr);
}
} else { /* Discard invalid addr class (see Note #3). */
NET_CTR_ERR_INC(NetIP_ErrTxDestCtr);
*perr = NET_IP_ERR_TX_DEST_INVALID;
return;
}
if (NetIP_AddrDfltGateway != NET_IP_ADDR_NONE) { /* If valid dflt gateway cfg'd, tx via dflt gateway. */
pbuf_hdr->IP_AddrNextHop = (CPU_INT32U)NetIP_AddrDfltGateway;
*perr = NET_IP_ERR_TX_DEST_DFLT_GATEWAY;
} else {
*perr = NET_IP_ERR_INVALID_ADDR_GATEWAY;
return;
}
}
/* ---------- CFG IP NEXT HOP NET-ORDER ADDR ---------- */
pbuf_hdr->IP_AddrNextHopNetOrder = NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrNextHop);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_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) : NetIP_Tx().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetIP_TxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr)
{
NET_CTR *pctr;
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
pctr = (NET_CTR *)&NetIP_ErrTxPktDiscardedCtr;
#else
pctr = (NET_CTR *) 0;
#endif
NetBuf_FreeBuf((NET_BUF *)pbuf,
(NET_CTR *)pctr);
*perr = NET_ERR_TX;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_ReTxPkt()
*
* Description : (1) Prepare & re-transmit IP packet :
*
* (a) Prepare IP header
* (b) Re-transmit IP packet datagram
*
*
* Argument(s) : pbuf Pointer to network buffer to re-transmit IP packet.
* ---- Argument checked in NetIP_ReTx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_ReTx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* -- RETURNED BY NetIP_ReTxPktPrepareHdr() : ---
* NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer.
* NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size.
*
* ---- RETURNED BY NetIP_TxPktDatagram() : -----
* NET_IP_ERR_NONE IP datagram successfully received & processed.
* NET_IF_ERR_NONE Packet successfully transmitted.
* NET_ERR_RX Receive error; packet discarded.
* NET_ERR_TX Transmit error; packet discarded.
* NET_IP_ERR_TX_DEST_INVALID Invalid transmit destination.
* NET_IP_ERR_INVALID_ADDR_HOST Invalid IP host address.
* NET_IP_ERR_INVALID_ADDR_NET Invalid IP net address.
* NET_IP_ERR_INVALID_ADDR_GATEWAY Invalid IP gateway address.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* Return(s) : none.
*
* Caller(s) : NetIP_ReTx().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetIP_ReTxPkt (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr)
{
/* ------------------ PREPARE IP HDR ------------------ */
NetIP_ReTxPktPrepareHdr(pbuf,
pbuf_hdr,
perr);
if (*perr != NET_IP_ERR_NONE) {
return;
}
/* -------------- RE-TX IP PKT DATAGRAM --------------- */
NetIP_TxPktDatagram(pbuf, pbuf_hdr, perr);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetIP_ReTxPktPrepareHdr()
*
* Description : (1) Prepare IP header for re-transmit IP packet :
*
* (a) Update network buffer's protocol & length controls.
*
* (b) (1) Prepare the re-transmit packet's following IP header fields :
*
* (A) Identification (ID) See Note #2
* (B) Check-Sum See Note #3
*
* (2) Assumes the following IP header fields are already validated/prepared &
* have NOT been modified :
*
* (A) Version
* (B) Header Length
* (C) Type of Service (TOS)
* (D) Total Length
* (E) Flags
* (F) Fragment Offset
* (G) Time-to-Live (TTL)
* (H) Protocol
* (I) Source Address
* (J) Destination Address
* (K) Options
*
* (c) Convert the following IP header fields from host-order to network-order :
*
* (1) Identification (ID)
* (2) Check-Sum See Note #3c
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit IP packet.
* ---- Argument checked in NetIP_Tx().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetIP_Tx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_IP_ERR_NONE IP header successfully prepared.
*
* - RETURNED BY NetUtil_16BitOnesCplChkSumHdrCalc() : -
* NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer.
* NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size.
*
* Return(s) : none.
*
* Caller(s) : NetIP_ReTxPkt().
*
* Note(s) : (2) RFC #1122, Section 3.2.1.5 states that "some Internet protocol experts have maintained
* that when a host sends an identical copy of an earlier datagram, the new copy should
* contain the same Identification value as the original ... However, ... we believe that
* retransmitting the same Identification field is not useful".
*
* (3) (a) IP header Check-Sum MUST be calculated AFTER the entire IP header 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) IP header Check-Sum field MUST be cleared to '0' BEFORE the IP header Check-Sum is
* calculated (see RFC #791, Section 3.1 'Header Checksum').
*
* (c) The IP header 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').
*********************************************************************************************************
*/
/*$PAGE*/
static void NetIP_ReTxPktPrepareHdr (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_IP_HDR *pip_hdr;
CPU_INT16U ip_id;
CPU_INT16U ip_hdr_len_tot;
CPU_INT16U ip_chk_sum;
/* ----------------- UPDATE BUF CTRLS ----------------- */
pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_IP; /* Update buf protocol for IP. */
/* Reset tot len for re-tx. */
pbuf_hdr->TotLen = (NET_BUF_SIZE)pbuf_hdr->IP_TotLen;
/* ------------------ PREPARE IP HDR ------------------ */
pip_hdr = (NET_IP_HDR *)&pbuf->Data[pbuf_hdr->IP_HdrIx];
/* ------------------ PREPARE IP ID ------------------- */
NET_IP_TX_GET_ID(ip_id); /* Get new IP ID (see Note #2). */
NET_UTIL_VAL_COPY_SET_NET_16(&pip_hdr->ID, &ip_id);
/* ---------------- PREPARE IP CHK SUM ---------------- */
/* See Note #3. */
NET_UTIL_VAL_SET_NET_16(&pip_hdr->ChkSum, 0x0000); /* Clr chk sum (see Note #3b). */
/* Calc chk sum. */
ip_hdr_len_tot = pbuf_hdr->IP_HdrLen;
ip_chk_sum = NetUtil_16BitOnesCplChkSumHdrCalc((void *)pip_hdr,
(CPU_INT16U)ip_hdr_len_tot,
(NET_ERR *)perr);
if (*perr != NET_UTIL_ERR_NONE) {
return;
}
NET_UTIL_VAL_COPY_16(&pip_hdr->ChkSum, &ip_chk_sum); /* Copy chk sum in net order (see Note #3c). */
*perr = NET_IP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
*********************************************************************************************************
* LAYER INTERFACE FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* NetARP_GetHostAddrPtrProtocol()
*
* Description : Get pointer to this host's internet protocol address.
*
* Argument(s) : none.
*
* Return(s) : Pointer to internet protocol address.
*
* Caller(s) : NetARP_Init().
*
* This function is an INTERNAL network protocol suite function & MUST NOT be called by
* application function(s).
*
* Note(s) : (1) ARP protocol address MUST be in network-order (see 'net_arp.c NetARP_CacheHandler()
* Note #2e3').
*********************************************************************************************************
*/
#ifdef NET_ARP_MODULE_PRESENT
CPU_INT08U *NetARP_GetHostAddrPtrProtocol (void)
{
CPU_INT08U *paddr;
paddr = (CPU_INT08U *)&NetIP_AddrThisHostNetOrder;
return (paddr);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_IsValidAddrProtocol()
*
* Description : Validate an ARP protocol address.
*
* Argument(s) : paddr_protocol Pointer to an ARP protocol address.
* -------------- Argument validated in NetARP_RxPktValidate().
*
* Return(s) : DEF_YES, if protocol address valid.
*
* DEF_NO, otherwise.
*
* Caller(s) : NetARP_RxPktValidate().
*
* This function is an INTERNAL network protocol suite function & SHOULD NOT be called by
* application function(s).
*
* Note(s) : none.
*********************************************************************************************************
*/
#ifdef NET_ARP_MODULE_PRESENT
CPU_BOOLEAN NetARP_IsValidAddrProtocol (CPU_INT08U *paddr_protocol)
{
NET_IP_ADDR addr;
CPU_BOOLEAN valid;
Mem_Copy((void *)&addr,
(void *)paddr_protocol,
(CPU_SIZE_T)NET_ARP_CFG_PROTOCOL_ADDR_LEN);
addr = NET_UTIL_NET_TO_HOST_32(addr);
valid = NetIP_IsValidAddrHost(addr);
return (valid);
}
#endif