/* ********************************************************************************************************* * 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 /*$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 ... * 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