/* ********************************************************************************************************* * 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 UDP LAYER * (USER DATAGRAM PROTOCOL) * * Filename : net_udp.c * Version : V1.89 * Programmer(s) : ITJ ********************************************************************************************************* * Note(s) : (1) Supports User Datagram Protocol as described in RFC #768. * ********************************************************************************************************* * Notice(s) : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given * us permission to reprint portions of their documentation. Portions of this text are * reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition, * Standard for Information Technology -- Portable Operating System Interface (POSIX), * The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute * of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any * discrepancy between these versions and the original IEEE and The Open Group Standard, * the original IEEE and The Open Group Standard is the referee document. The original * Standard can be obtained online at http://www.opengroup.org/unix/online.html. ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #define NET_UDP_MODULE #include /*$PAGE*/ /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL DATA TYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL GLOBAL VARIABLES ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ /* --------------- RX FNCTS --------------- */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetUDP_RxPktValidateBuf (NET_BUF_HDR *pbuf_hdr, NET_ERR *perr); #endif static void NetUDP_RxPktValidate (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_UDP_HDR *pudp_hdr, NET_ERR *perr); static void NetUDP_RxPktDemuxDatagram(NET_BUF *pbuf, NET_ERR *perr); #if ((NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_APP ) || \ (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK_APP)) static void NetUDP_RxPktDemuxAppData (NET_BUF *pbuf, NET_ERR *perr); #endif static void NetUDP_RxPktFree (NET_BUF *pbuf); static void NetUDP_RxPktDiscard (NET_BUF *pbuf, NET_ERR *perr); /* --------------- TX FNCTS --------------- */ static void NetUDP_Tx (NET_BUF *pbuf, NET_IP_ADDR src_addr, NET_UDP_PORT_NBR src_port, NET_IP_ADDR dest_addr, NET_UDP_PORT_NBR dest_port, NET_IP_TOS TOS, NET_IP_TTL TTL, CPU_INT16U flags_udp, CPU_INT16U flags_ip, void *popts_ip, NET_ERR *perr); #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetUDP_TxPktValidate (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_UDP_PORT_NBR src_port, NET_UDP_PORT_NBR dest_port, CPU_INT16U flags_udp, NET_ERR *perr); #endif static void NetUDP_TxPktPrepareHdr (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_IP_ADDR src_addr, NET_UDP_PORT_NBR src_port, NET_IP_ADDR dest_addr, NET_UDP_PORT_NBR dest_port, CPU_INT16U flags_udp, NET_ERR *perr); static void NetUDP_TxPktFree (NET_BUF *pbuf); static void NetUDP_TxPktDiscard (NET_BUF *pbuf); /* ********************************************************************************************************* * LOCAL CONFIGURATION ERRORS ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_Init() * * Description : (1) Initialize User Datagram Protocol Layer : * * (a) Initialize UDP 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 NetUDP_Init (void) { /* ------------- INIT UDP STAT & ERR CTRS ------------- */ #if (NET_CTR_CFG_STAT_EN == DEF_ENABLED) NetUDP_StatRxPktCtr = 0; NetUDP_StatRxDatagramProcessedCtr = 0; NetUDP_StatTxDatagramCtr = 0; #endif #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) NetUDP_ErrNullPtrCtr = 0; NetUDP_ErrInvalidFlagsCtr = 0; NetUDP_ErrRxHdrDatagramLenCtr = 0; NetUDP_ErrRxHdrPortSrcCtr = 0; NetUDP_ErrRxHdrPortDestCtr = 0; NetUDP_ErrRxHdrChkSumCtr = 0; NetUDP_ErrRxDestCtr = 0; NetUDP_ErrRxPktDiscardedCtr = 0; NetUDP_ErrTxPktDiscardedCtr = 0; #if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \ (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)) NetUDP_ErrTxInvalidSizeCtr = 0; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetUDP_ErrRxInvalidBufIxCtr = 0; NetUDP_ErrRxHdrDataLenCtr = 0; NetUDP_ErrTxProtocolCtr = 0; NetUDP_ErrTxInvalidBufIxCtr = 0; NetUDP_ErrTxHdrDataLenCtr = 0; NetUDP_ErrTxHdrPortSrcCtr = 0; NetUDP_ErrTxHdrPortDestCtr = 0; NetUDP_ErrTxHdrFlagsCtr = 0; #endif #endif } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_Rx() * * Description : (1) Process received datagrams & forward to socket or application layer : * * (a) Validate UDP packet * (b) Demultiplex datagram to socket/application connection * (c) Update receive statistics * * (2) Although UDP data units are typically referred to as 'datagrams' (see RFC #768, Section * 'Introduction'), the term 'UDP packet' (see RFC #1983, 'packet') is used for UDP Receive * until the packet is validated as a UDP datagram. * * * Argument(s) : pbuf Pointer to network buffer that received UDP packet. * * perr Pointer to variable that will receive the return error code from this function : * * NET_UDP_ERR_NONE UDP datagram successfully received & processed. * NET_ERR_INIT_INCOMPLETE Network initialization NOT complete. * * ----- RETURNED BY NetUDP_RxPktDiscard() : ----- * NET_ERR_RX Receive error; packet discarded. * * Return(s) : none. * * Caller(s) : NetIP_RxPktDemuxDatagram(). * * This function is an INTERNAL network protocol suite function & MUST NOT be called by * application function(s). * * Note(s) : (3) NetUDP_Rx() blocked until network initialization completes. * * (4) Network buffer already freed by higher layer; only increment error counter. * * (5) RFC #792, Section 'Destination Unreachable Message : Description' states that * "if, in the destination host, the IP module cannot deliver the datagram because * the indicated ... process port is not active, the destination host may send a * destination unreachable message to the source host". ********************************************************************************************************* */ /*$PAGE*/ void NetUDP_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_UDP_HDR *pudp_hdr; NET_ERR msg_err; #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) { NetUDP_RxPktDiscard(pbuf, perr); NET_CTR_ERR_INC(NetUDP_ErrNullPtrCtr); return; } #endif NET_CTR_STAT_INC(NetUDP_StatRxPktCtr); /* ----------------- VALIDATE UDP PKT ----------------- */ pbuf_hdr = &pbuf->Hdr; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetUDP_RxPktValidateBuf(pbuf_hdr, perr); /* Validate rx'd buf. */ switch (*perr) { case NET_UDP_ERR_NONE: break; case NET_ERR_INVALID_PROTOCOL: case NET_BUF_ERR_INVALID_IX: default: NetUDP_RxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif pudp_hdr = (NET_UDP_HDR *)&pbuf->Data[pbuf_hdr->TCP_UDP_HdrDataIx]; NetUDP_RxPktValidate(pbuf, pbuf_hdr, pudp_hdr, perr); /* Validate rx'd pkt. */ /* ------------------ DEMUX DATAGRAM ------------------ */ switch (*perr) { case NET_UDP_ERR_NONE: NetUDP_RxPktDemuxDatagram(pbuf, perr); break; case NET_UDP_ERR_INVALID_PORT_NBR: case NET_UDP_ERR_INVALID_LEN: case NET_UDP_ERR_INVALID_LEN_DATA: case NET_UDP_ERR_INVALID_CHK_SUM: default: NetUDP_RxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } /*$PAGE*/ /* ----------------- UPDATE RX STATS ------------------ */ switch (*perr) { /* Chk err from NetUDP_RxPktDemuxDatagram(). */ case NET_APP_ERR_NONE: case NET_SOCK_ERR_NONE: NET_CTR_STAT_INC(NetUDP_StatRxDatagramProcessedCtr); *perr = NET_UDP_ERR_NONE; break; case NET_ERR_RX: NET_CTR_ERR_INC(NetUDP_ErrRxPktDiscardedCtr); /* See Note #4. */ return; /* Prevent 'break NOT reachable' compiler warning. */ case NET_ERR_RX_DEST: NET_CTR_ERR_INC(NetUDP_ErrRxDestCtr); /* Tx ICMP port unreach (see Note #5). */ NetICMP_TxMsgErr(pbuf, NET_ICMP_MSG_TYPE_DEST_UNREACH, NET_ICMP_MSG_CODE_DEST_PORT, NET_ICMP_MSG_PTR_NONE, &msg_err); NetUDP_RxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ case NET_ERR_INIT_INCOMPLETE: default: NetUDP_RxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_RxAppData() * * Description : (1) Deframe application data from received UDP packet buffer(s) : * * (a) Validate receive packet buffer(s) * (b) Validate receive data buffer See Note #4 * (c) Validate receive flags See Note #5 * (d) Get any received IP options See Note #6 * (e) Deframe application data from UDP packet buffer(s) * (f) Free UDP packet buffer(s) * * * Argument(s) : pbuf Pointer to network buffer that received UDP datagram. * * pdata_buf Pointer to application buffer to receive application data. * * data_buf_len Size of application receive buffer (in octets) [see Note #4]. * * flags Flags to select receive options (see Note #5); bit-field flags logically OR'd : * * NET_UDP_FLAG_NONE No UDP receive flags selected. * NET_UDP_FLAG_RX_DATA_PEEK Receive UDP application data without consuming * the data; i.e. do NOT free any UDP receive * packet buffer(s). * * pip_opts_buf Pointer to buffer to receive possible IP options (see Note #6a), if NO errors. * * ip_opts_buf_len Size of IP options receive buffer (in octets) [see Note #6b]. * * pip_opts_len Pointer to variable that will receive the return size of any received IP options, * if NO errors. * * perr Pointer to variable that will receive the return error code from this function : * * NET_UDP_ERR_NONE UDP application data successfully deframed; check * return value for number of data octets received. * NET_UDP_ERR_INVALID_DATA_SIZE UDP data receive buffer insufficient size; some, * but not all, UDP application data deframed * into receive buffer (see Note #4b). * * NET_ERR_INIT_INCOMPLETE Network initialization NOT complete. * NET_UDP_ERR_NULL_PTR Argument 'pbuf'/'pdata_buf' passed a NULL pointer. * NET_UDP_ERR_INVALID_FLAG Invalid UDP flags. * * ------- RETURNED BY NetUDP_RxPktDiscard() : -------- * NET_ERR_RX Receive error; packet discarded. * * Return(s) : Total application data octets deframed into receive buffer, if NO errors. * * 0, otherwise. * * Caller(s) : NetSock_RxDataHandlerDatagram(), * NetUDP_RxAppDataHandler(). * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). *$PAGE* * Note(s) : (2) NetUDP_RxAppData() MUST be called with the global network lock already acquired. * * See also 'NetUDP_RxPktDemuxAppData() Note #1a1A1b'. * * (3) NetUDP_RxAppData() blocked until network initialization completes. * * (4) (a) Application data receive buffer should be large enough to receive either ... * * (1) The maximum UDP datagram size (i.e. 65,507 octets) * OR * (2) The application's expected maximum UDP datagram size * * (b) If the application receive buffer size is NOT large enough for the received UDP datagram, * the remaining application data octets are discarded & NET_UDP_ERR_INVALID_DATA_SIZE error * is returned. * * (5) If UDP receive flag options that are NOT implemented are requested, NetUDP_RxAppData() aborts * & returns appropriate error codes so that requested flag options are NOT silently ignored. * * (6) (a) If ... * * (1) NO IP options were received with the UDP datagram * OR * (2) NO IP options receive buffer is provided by the application * OR * (3) IP options receive buffer NOT large enough for the received IP options * * ... then NO IP options are returned & any received IP options are silently discarded. * * (b) The IP options receive buffer size SHOULD be large enough to receive the maximum * IP options size, NET_IP_HDR_OPT_SIZE_MAX. * * (c) IP options are received from the first packet buffer. In other words, if multiple * packet buffers are received for a fragmented datagram, IP options are received from * the first fragment of the datagram. * * (d) #### Received IP options should be provided/decoded via appropriate IP layer API. * * (7) Pointers to variables that return length or size values MUST be initialized to return * zero PRIOR to all other validation or function handling in case of any error(s). * * (8) Since pointer arithmetic is based on the specific pointer data type & inherent pointer * data type size, pointer arithmetic operands : * * (a) MUST be in terms of the specific pointer data type & data type size; ... * (b) SHOULD NOT & in some cases MUST NOT be cast to other data types or data type sizes. * * (9) (a) On any internal receive errors, UDP receive packets are discarded. * * (b) On any external application errors, UDP receive packets are NOT discarded; * the application MAY continue to attempt to receive the application data * via NetUDP_RxAppData(). * * (10) #### IP options arguments may NOT be necessary. ********************************************************************************************************* */ /*$PAGE*/ CPU_INT16U NetUDP_RxAppData (NET_BUF *pbuf, void *pdata_buf, CPU_INT16U data_buf_len, CPU_INT16U flags, void *pip_opts_buf, CPU_INT08U ip_opts_buf_len, CPU_INT08U *pip_opts_len, NET_ERR *perr) { #if (((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \ (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \ (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)) CPU_INT16U flag_mask; CPU_BOOLEAN used; #endif CPU_BOOLEAN peek; NET_BUF *pbuf_head; NET_BUF *pbuf_next; NET_BUF_HDR *pbuf_head_hdr; NET_BUF_HDR *pbuf_hdr; NET_BUF_SIZE data_len_pkt; CPU_INT16U data_len_buf_rem; CPU_INT16U data_len_tot; CPU_INT08U *p_data; CPU_INT08U *pip_opts; CPU_INT08U ip_opt_len; NET_ERR err; NET_ERR err_rtn; if (pip_opts_len != (CPU_INT08U *)0) { /* Init len for err (see Note #7). */ *pip_opts_len = 0; } #if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \ (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)) if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit rx (see Notes #3 & #9b). */ *perr = NET_ERR_INIT_INCOMPLETE; return (0); } /* --------------- VALIDATE RX PKT BUFS --------------- */ if (pbuf == (NET_BUF *)0) { *perr = NET_UDP_ERR_NULL_PTR; /* See Note #9b. */ return (0); } used = NetBuf_IsUsed(pbuf); if (used != DEF_YES) { NET_CTR_ERR_INC(NetUDP_ErrRxPktDiscardedCtr); *perr = NET_ERR_RX; /* See Note #9b. */ return (0); } /* --------------- VALIDATE RX DATA BUF --------------- */ if (pdata_buf == (CPU_INT08U *)0) { *perr = NET_UDP_ERR_NULL_PTR; /* See Note #9b. */ return (0); } if (data_buf_len < 1) { *perr = NET_UDP_ERR_INVALID_DATA_SIZE; /* See Note #9b. */ return (0); } /* ---------------- VALIDATE RX FLAGS ----------------- */ flag_mask = NET_UDP_FLAG_NONE | NET_UDP_FLAG_RX_DATA_PEEK; if ((flags & ~flag_mask) != NET_UDP_FLAG_NONE) { /* If any invalid flags req'd, rtn err (see Note #5). */ NET_CTR_ERR_INC(NetUDP_ErrInvalidFlagsCtr); *perr = NET_UDP_ERR_INVALID_FLAG; /* See Note #9b. */ return (0); } #endif /*$PAGE*/ /* ----------------- GET RX'D IP OPTS ----------------- */ /* See Note #6. */ pbuf_hdr = &pbuf->Hdr; if (pbuf_hdr->IP_OptPtr != (void *)0) { /* If IP opts rx'd, & ... */ if (pip_opts_buf != (void *)0) { /* .. IP opts rx buf avail, & ... */ if (ip_opts_buf_len >= pbuf_hdr->IP_HdrLen) { /* .. IP opts rx buf size sufficient, ... */ pip_opts = &pbuf->Data[pbuf_hdr->IP_HdrIx]; ip_opt_len = (CPU_INT08U)pbuf_hdr->IP_HdrLen; Mem_Copy((void *)pip_opts_buf, /* .. copy IP opts into rx buf. */ (void *)pip_opts, (CPU_SIZE_T) ip_opt_len); *pip_opts_len = ip_opt_len; } } } /* ------------- DEFRAME UDP APP RX DATA -------------- */ pbuf_head = (NET_BUF *) pbuf; pbuf_head_hdr = (NET_BUF_HDR *)&pbuf_head->Hdr; p_data = (CPU_INT08U *) pdata_buf; data_len_buf_rem = (CPU_INT16U ) data_buf_len; data_len_tot = (CPU_INT16U ) 0; err_rtn = NET_UDP_ERR_NONE; while ((pbuf != (NET_BUF *)0) && /* Copy app rx data from avail pkt buf(s). */ (data_len_buf_rem > 0)) { pbuf_hdr = &pbuf->Hdr; pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr; if (data_len_buf_rem > pbuf_hdr->DataLen) { /* If rem data buf len > pkt buf data len, ... */ data_len_pkt = pbuf_hdr->DataLen; /* ... copy all pkt buf data len. */ } else { data_len_pkt = (NET_BUF_SIZE)data_len_buf_rem; /* Else limit copy to rem data buf len ... */ err_rtn = NET_UDP_ERR_INVALID_DATA_SIZE; /* ... & rtn data size err code (see Note #4b). */ } NetBuf_DataRd((NET_BUF *) pbuf, (NET_BUF_SIZE) pbuf_hdr->DataIx, (NET_BUF_SIZE) data_len_pkt, (CPU_INT08U *) p_data, (NET_ERR *)&err); if (err != NET_BUF_ERR_NONE) { /* See Note #9a. */ NetUDP_RxPktDiscard(pbuf_head, perr); return (0); } /* Update data ptr & lens. */ p_data += data_len_pkt; /* MUST NOT cast ptr operand (see Note #8b). */ data_len_tot += (CPU_INT16U)data_len_pkt; data_len_buf_rem -= (CPU_INT16U)data_len_pkt; pbuf = pbuf_next; } /* ----------------- FREE UDP RX PKTS ----------------- */ peek = DEF_BIT_IS_SET(flags, NET_UDP_FLAG_RX_DATA_PEEK); if (peek != DEF_YES) { /* If peek opt NOT req'd, pkt buf(s) consumed : ... */ pbuf_head_hdr->NextPrimListPtr = (void *)0; /* ... unlink from any other pkt bufs/chains ... */ NetUDP_RxPktFree(pbuf_head); /* ... & free pkt buf(s). */ } *perr = err_rtn; return (data_len_tot); } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_TxAppData() * * Description : (1) Prepare & transmit data from Application layer(s) via UDP layer : * * (a) Validate application data * (b) Transmit application data via UDP Transmit : * (1) Calculate/validate application data buffer size * (2) Get buffer(s) for application data * (3) Copy application data into UDP packet buffer(s) * (4) Initialize UDP packet buffer controls * (5) Free UDP packet buffer(s) * * * Argument(s) : p_data Pointer to application data. * * data_len Length of application data (in octets) [see Note #6]. * * src_addr Source IP address. * * src_port Source UDP port. * * dest_addr Destination IP address. * * dest_port Destination UDP port. * * TOS Specific TOS to transmit UDP/IP packet * (see 'net_ip.h IP HEADER TYPE OF SERVICE (TOS) DEFINES'). * * TTL Specific TTL to transmit UDP/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_udp Flags to select UDP transmit options (see Note #4); bit-field flags logically OR'd : * * NET_UDP_FLAG_NONE No UDP transmit flags selected. * NET_UDP_FLAG_TX_CHK_SUM_DIS DISABLE transmit check-sums. * NET_UDP_FLAG_TX_BLOCK Transmit UDP application data with blocking, * if flag set; without blocking, if clear * (see Note #4a). * * flags_ip Flags to select IP 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_ip Pointer to one or more IP options configuration data structures (see Note #5) : * * 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_UDP_ERR_NONE Application data successfully prepared & * transmitted via UDP layer. * NET_ERR_INIT_INCOMPLETE Network initialization NOT complete. * NET_UDP_ERR_NULL_PTR Argument 'p_data' passed a NULL pointer. * NET_UDP_ERR_INVALID_DATA_SIZE Argument 'data_len' passed an invalid size * (see Notes #6b & #6a2B). * * ----------- RETURNED BY NetBuf_Get() : ----------- * NET_BUF_ERR_INVALID_SIZE Requested size is greater then the maximum buffer * size available. * NET_BUF_ERR_INVALID_LEN Requested size & start index calculation overflows * buffer's DATA area. * NET_BUF_ERR_INVALID_TYPE Invalid buffer type. * NET_BUF_ERR_NONE_AVAIL NO available buffers to allocate. * * --------- RETURNED BY NetBuf_DataWr() : ---------- * NET_BUF_ERR_NULL_PTR Argument(s) passed a NULL pointer. * NET_BUF_ERR_INVALID_IX Invalid buffer index. * * ----------- RETURNED BY NetUDP_Tx() : ------------ * NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type. * NET_UDP_ERR_INVALID_LEN_DATA Invalid protocol/data length. * NET_UDP_ERR_INVALID_PORT_NBR Invalid UDP port number. * NET_UDP_ERR_INVALID_FLAG Invalid UDP flag(s). * NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer. * NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size. * NET_UTIL_ERR_INVALID_PROTOCOL Invalid data packet protocol. * NET_ERR_TX Transmit error; packet(s) discarded. *$PAGE* * Return(s) : Number of data octets transmitted, if NO errors. * * 0, otherwise. * * Caller(s) : NetSock_TxDataHandlerDatagram(), * Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : (2) NetUDP_TxAppData() MUST be called with the global network lock already acquired. * * (3) NetUDP_TxAppData() blocked until network initialization completes. * * (4) #### Some UDP transmit flag options NOT yet implemented : * * (a) NET_UDP_FLAG_TX_BLOCK * * See also 'NetUDP_TxPktValidate() Note #2b'. * * (5) #### 'popts' configuration should be provided via appropriate IP layer API. * * (6) (a) (1) Datagram transmission & reception MUST be atomic -- i.e. every single, complete * datagram transmitted SHOULD be received as a single, complete datagram. Thus, * each call to transmit data MUST be transmitted in a single, complete datagram. * * (2) (A) IEEE Std 1003.1, 2004 Edition, Section 'send() : DESCRIPTION' states that * "if the message is too long to pass through the underlying protocol, send() * shall fail and no data shall be transmitted". * * (B) Since IP transmit fragmentation is NOT currently supported (see 'net_ip.h * Note #1e'), if the requested datagram transmit data length is greater than * the UDP MTU, then NO data is transmitted & NET_UDP_ERR_INVALID_DATA_SIZE * error is returned. * * (b) 'data_len' of 0 octets NOT allowed. * * (7) On ANY transmit error, any remaining application data transmit is immediately aborted. * * (8) Network buffer already freed by lower layer; only increment error counter. ********************************************************************************************************* */ CPU_INT16U NetUDP_TxAppData (void *p_data, CPU_INT16U data_len, NET_IP_ADDR src_addr, NET_UDP_PORT_NBR src_port, NET_IP_ADDR dest_addr, NET_UDP_PORT_NBR dest_port, NET_IP_TOS TOS, NET_IP_TTL TTL, CPU_INT16U flags_udp, CPU_INT16U flags_ip, void *popts_ip, NET_ERR *perr) { #if (((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \ (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF *pbuf; NET_BUF_HDR *pbuf_hdr; NET_BUF_SIZE buf_size_max; NET_BUF_SIZE buf_size_max_data; NET_BUF_SIZE data_ix_pkt; NET_BUF_SIZE data_len_pkt; CPU_INT16U data_len_tot; CPU_INT08U *p_data_pkt; #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit tx (see Note #3). */ *perr = NET_ERR_INIT_INCOMPLETE; return (0); } #endif /*$PAGE*/ #if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \ (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)) /* ---------------- VALIDATE APP DATA ----------------- */ if (p_data == (void *)0) { *perr = NET_UDP_ERR_NULL_PTR; return (0); } if (data_len < 1) { /* Validate data len (see Note #6b). */ NET_CTR_ERR_INC(NetUDP_ErrTxInvalidSizeCtr); *perr = NET_UDP_ERR_INVALID_DATA_SIZE; return (0); } #endif /* ------------------- TX APP DATA -------------------- */ /* Calc buf max data size. */ data_ix_pkt = NET_BUF_DATA_TX_IX; buf_size_max = NetBuf_GetMaxSize((NET_BUF *)0, (NET_BUF_SIZE)data_ix_pkt); buf_size_max_data = DEF_MIN(buf_size_max, NET_UDP_MTU); if (data_len > buf_size_max_data) { /* If data len > max data size, abort tx ... */ *perr = NET_UDP_ERR_INVALID_DATA_SIZE; /* ... & rtn size err (see Note #6a2B). */ return (0); } else { /* Else limit pkt data len to data len. */ data_len_pkt = (NET_BUF_SIZE)data_len; } data_len_tot = 0; p_data_pkt = (CPU_INT08U *)p_data; pbuf = NetBuf_Get((NET_BUF_SIZE)data_len_pkt, /* Get app data tx buf. */ (NET_BUF_SIZE)data_ix_pkt, (CPU_INT16U )NET_BUF_FLAG_NONE, (NET_ERR *)perr); if (*perr != NET_BUF_ERR_NONE) { NetUDP_TxPktDiscard(pbuf); return (data_len_tot); } NetBuf_DataWr((NET_BUF *)pbuf, /* Wr app data into app data tx buf. */ (NET_BUF_SIZE)data_ix_pkt, (NET_BUF_SIZE)data_len_pkt, (CPU_INT08U *)p_data_pkt, (NET_ERR *)perr); if (*perr != NET_BUF_ERR_NONE) { NetUDP_TxPktDiscard(pbuf); return (data_len_tot); } /* Init app data tx buf ctrls. */ pbuf_hdr = &pbuf->Hdr; pbuf_hdr->DataIx = (CPU_INT16U )data_ix_pkt; pbuf_hdr->DataLen = (NET_BUF_SIZE)data_len_pkt; pbuf_hdr->TotLen = (NET_BUF_SIZE)pbuf_hdr->DataLen; pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_APP; NetUDP_Tx(pbuf, /* Tx app data buf via UDP tx. */ src_addr, src_port, dest_addr, dest_port, TOS, TTL, flags_udp, flags_ip, popts_ip, perr); if (*perr != NET_UDP_ERR_NONE) { return (data_len_tot); } NetUDP_TxPktFree(pbuf); /* Free app data tx buf. */ data_len_tot += data_len_pkt; /* Calc tot app data len tx'd. */ *perr = NET_UDP_ERR_NONE; return (data_len_tot); } /*$PAGE*/ /* ********************************************************************************************************* ********************************************************************************************************* * LOCAL FUNCTIONS ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * NetUDP_RxPktValidateBuf() * * Description : Validate received buffer header as UDP protocol. * * Argument(s) : pbuf_hdr Pointer to network buffer header that received UDP packet. * -------- Argument validated in NetUDP_Rx(). * * perr Pointer to variable that will receive the return error code from this function : * * NET_UDP_ERR_NONE Received buffer's UDP header validated. * NET_ERR_INVALID_PROTOCOL Buffer's protocol type is NOT UDP. * NET_BUF_ERR_INVALID_IX Invalid buffer index. * * Return(s) : none. * * Caller(s) : NetUDP_Rx(). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetUDP_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 UDP BUF HDR --------------- */ if (pbuf_hdr->ProtocolHdrType != NET_PROTOCOL_TYPE_UDP) { NET_CTR_ERR_INC(Net_ErrInvalidProtocolCtr); *perr = NET_ERR_INVALID_PROTOCOL; return; } if (pbuf_hdr->TCP_UDP_HdrDataIx == NET_BUF_IX_NONE) { NET_CTR_ERR_INC(NetUDP_ErrRxInvalidBufIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } *perr = NET_UDP_ERR_NONE; } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_RxPktValidate() * * Description : (1) Validate received UDP packet : * * (a) Validate the received packet's following UDP header fields : * * (1) Source Port * (2) Destination Port * (3) Datagram Length See Note #3 * (4) Check-Sum See Note #4 * * (b) Convert the following UDP header fields from network-order to host-order : * * (1) Source Port See Notes #1bB1 * (2) Destination Port See Notes #1bB2 * (3) Datagram Length See Notes #1bB3 * (4) Check-Sum See Note #4d * * (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 UDP header fields are converted & stored in network buffer * variables : * * (1) Source Port * (2) Destination Port * (3) Datagram Length * * (c) Update network buffer's protocol controls. * * * Argument(s) : pbuf Pointer to network buffer that received UDP packet. * ---- Argument checked in NetUDP_Rx(). * * pbuf_hdr Pointer to network buffer header. * -------- Argument validated in NetUDP_Rx(). * * pudp_hdr Pointer to received packet's UDP header. * -------- Argument validated in NetUDP_Rx()/NetUDP_RxPktValidateBuf(). * * perr Pointer to variable that will receive the return error code from this function : * * NET_UDP_ERR_NONE Received packet validated. * NET_UDP_ERR_INVALID_PORT_NBR Invalid UDP port number. * NET_UDP_ERR_INVALID_LEN Invalid UDP datagram length. * NET_UDP_ERR_INVALID_LEN_DATA Invalid UDP datagram data length. * NET_UDP_ERR_INVALID_CHK_SUM Invalid UDP check-sum. * * Return(s) : none. * * Caller(s) : NetUDP_Rx(). *$PAGE* * Note(s) : (2) See 'net_udp.h UDP HEADER' for UDP header format. * * (3) In addition to validating that the UDP Datagram Length is greater than or equal to the * minimum UDP header length, the UDP Datagram Length is compared to the remaining IP * Datagram Length which should be identical. * * (4) (a) UDP 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 UDP Datagram 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, UDP Datagram Check-Sum may be * validated at any point. * * (c) The UDP Datagram Check-Sum MUST be validated AFTER the datagram length field has been * validated so that the total UDP Datagram Length (in octets) will already be calculated * for the UDP Check-Sum calculation. * * For efficiency, the UDP Datagram Check-Sum is validated AFTER all other UDP header * fields have been validated. Thus, the iteration-intensive UDP Datagram Check-Sum is * calculated only after all other UDP header fields have been quickly validated. * * (d) (1) Before the UDP Datagram Check-Sum is validated, it is necessary to convert the * Check-Sum from network-order to host-order to verify whether the received UDP * datagram's Check-Sum is valid -- i.e. whether the UDP datagram was transmitted * with or without a computed Check-Sum (see RFC #768, Section 'Fields : Checksum'). * * (2) Since the value that indicates no check-sum was computed for the received UDP * datagram is one's-complement positive zero -- all check-sum bits equal to zero, * a value that is endian-order independent -- it is NOT absolutely necessary to * convert the UDP Datagram Check-Sum from network-order to host-order. * * However, network data value macro's inherently convert data words from network * word order to CPU word order. * * See also 'net_util.h NETWORK DATA VALUE MACRO'S Note #1a1'. * * (3) (A) Any UDP datagram received with NO computed check-sum is flagged so that "an * application MAY optionally ... discard ... datagrams without checksums" (see * RFC #1122, Section 4.1.3.4). * * (B) UDP buffer flag value to clear was previously initialized in NetBuf_Get() when * the buffer was allocated. This buffer flag value does NOT need to be re-cleared * but is shown for completeness. * * (e) (1) In addition to the UDP datagram header & data, the UDP Check-Sum calculation * includes "a pseudo header of information from the IP header ... conceptually * prefixed to the UDP header [which] contains the source address, the destination * address, the protocol, and the UDP length" (see RFC #768, Section 'Fields : * Checksum'). * * (2) Since network check-sum functions REQUIRE that 16-bit one's-complement check- * sum calculations be performed on headers & data arranged in network-order (see * 'net_util.c NetUtil_16BitOnesCplChkSumDataVerify() Note #4'), UDP pseudo-header * values MUST be set or converted to network-order. * * (f) RFC #768, Section 'Fields : Checksum' specifies that "the data [is] padded with zero * octets at the end (if necessary) to make a multiple of two octets". * * See also 'net_util.c NetUtil_16BitSumDataCalc() Note #8'. * * (5) (a) Since the minimum network buffer size MUST be configured such that the entire UDP * header MUST be received in a single packet (see 'net_buf.h NETWORK BUFFER INDEX & * SIZE DEFINES Note #1c'), after the UDP header size is decremented from the first * packet buffer's remaining number of data octets, any remaining octets MUST be user * &/or application data octets. * * (1) Note that the 'Data' index is updated regardless of a null-size data length. * * (b) If additional packet buffers exist, the remaining IP datagram 'Data' MUST be user * &/or application data. Therefore, the 'Data' length does NOT need to be adjusted * but the 'Data' index MUST be updated. * * (c) #### Total UDP Datagram Length & Data Length is duplicated in ALL fragmented packet * buffers (may NOT be necessary; remove if unnecessary). * * (6) RFC #1122, Sections 3.2.1 & 3.2.2 require that IP & ICMP packets with certain invalid * header fields be "silently discarded". However, NO RFC specifies how UDP should handle * received datagrams with invalid header fields. * * In addition, UDP is a "transaction oriented" protocol that does NOT guarantee "delivery * and duplicate protection" of UDP datagrams (see RFC #768, Section 'Introduction'). * * Therefore, it is assumed that ALL UDP datagrams with ANY invalid header fields SHOULD * be silently discarded. ********************************************************************************************************* */ /*$PAGE*/ static void NetUDP_RxPktValidate (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_UDP_HDR *pudp_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_INT16U udp_tot_len; CPU_INT16U udp_data_len; NET_CHK_SUM udp_chk_sum; CPU_BOOLEAN udp_chk_sum_valid; NET_UDP_PSEUDO_HDR udp_pseudo_hdr; NET_BUF *pbuf_next; NET_BUF_HDR *pbuf_next_hdr; /* ---------------- VALIDATE UDP PORTS ---------------- */ NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->TCP_UDP_PortSrc, &pudp_hdr->PortSrc); if (pbuf_hdr->TCP_UDP_PortSrc == NET_UDP_PORT_NBR_RESERVED) { NET_CTR_ERR_INC(NetUDP_ErrRxHdrPortSrcCtr); *perr = NET_UDP_ERR_INVALID_PORT_NBR; return; } NET_UTIL_VAL_COPY_GET_NET_16(&pbuf_hdr->TCP_UDP_PortDest, &pudp_hdr->PortDest); if (pbuf_hdr->TCP_UDP_PortDest == NET_UDP_PORT_NBR_RESERVED) { NET_CTR_ERR_INC(NetUDP_ErrRxHdrPortDestCtr); *perr = NET_UDP_ERR_INVALID_PORT_NBR; return; } /* ------------ VALIDATE UDP DATAGRAM LEN ------------- */ /* See Note #3. */ NET_UTIL_VAL_COPY_GET_NET_16(&udp_tot_len, &pudp_hdr->DatagramLen); pbuf_hdr->TCP_UDP_TotLen = udp_tot_len; if (pbuf_hdr->TCP_UDP_TotLen < NET_UDP_TOT_LEN_MIN) { /* If datagram len < min tot len, rtn err. */ NET_CTR_ERR_INC(NetUDP_ErrRxHdrDatagramLenCtr); *perr = NET_UDP_ERR_INVALID_LEN; return; } if (pbuf_hdr->TCP_UDP_TotLen > NET_UDP_TOT_LEN_MAX) { /* If datagram len > max tot len, rtn err. */ NET_CTR_ERR_INC(NetUDP_ErrRxHdrDatagramLenCtr); *perr = NET_UDP_ERR_INVALID_LEN; return; } if (pbuf_hdr->TCP_UDP_TotLen != pbuf_hdr->IP_DatagramLen) { /* If datagram len != IP datagram len, rtn err. */ NET_CTR_ERR_INC(NetUDP_ErrRxHdrDatagramLenCtr); *perr = NET_UDP_ERR_INVALID_LEN; return; } /*$PAGE*/ /* --------------- VALIDATE UDP CHK SUM --------------- */ /* See Note #4. */ NET_UTIL_VAL_COPY_GET_NET_16(&udp_chk_sum, &pudp_hdr->ChkSum); if (udp_chk_sum != NET_UDP_HDR_CHK_SUM_NONE) { /* If chk sum rx'd, verify chk sum (see Note #4d). */ /* Prepare UDP chk sum pseudo-hdr (see Note #4e). */ udp_pseudo_hdr.AddrSrc = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrSrc); udp_pseudo_hdr.AddrDest = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(pbuf_hdr->IP_AddrDest); udp_pseudo_hdr.Zero = (CPU_INT08U )0x00; udp_pseudo_hdr.Protocol = (CPU_INT08U )NET_IP_HDR_PROTOCOL_UDP; udp_pseudo_hdr.DatagramLen = (CPU_INT16U )NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_TotLen); udp_chk_sum_valid = NetUtil_16BitOnesCplChkSumDataVerify((void *) pbuf, (void *)&udp_pseudo_hdr, (CPU_INT16U) NET_UDP_PSEUDO_HDR_SIZE, (NET_ERR *) perr); if (udp_chk_sum_valid != DEF_OK) { NET_CTR_ERR_INC(NetUDP_ErrRxHdrChkSumCtr); *perr = NET_UDP_ERR_INVALID_CHK_SUM; return; } DEF_BIT_SET(pbuf_hdr->Flags, NET_BUF_FLAG_UDP_RX_CHK_SUM_VALID); } else { /* Else discard or flag NO rx'd chk sum (see Note #4d3).*/ #if (NET_UDP_CFG_RX_CHK_SUM_DISCARD_EN != DEF_DISABLED) NET_CTR_ERR_INC(NetUDP_ErrRxHdrChkSumCtr); *perr = NET_UDP_ERR_INVALID_CHK_SUM; return; #endif #if 0 /* Clr'd in NetBuf_Get() [see Note #4d3B]. */ DEF_BIT_CLR(pbuf_hdr->Flags, NET_BUF_FLAG_UDP_RX_CHK_SUM_VALID); #endif } /* ----------------- UPDATE BUF CTRLS ----------------- */ /* Calc UDP data len/ix (see Note #5a). */ pbuf_hdr->TCP_UDP_HdrLen = NET_UDP_HDR_SIZE; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) if (pbuf_hdr->TCP_UDP_HdrLen > udp_tot_len) { NET_CTR_ERR_INC(NetUDP_ErrRxHdrDataLenCtr); *perr = NET_UDP_ERR_INVALID_LEN_DATA; return; } if (pbuf_hdr->TCP_UDP_HdrLen > pbuf_hdr->DataLen) { NET_CTR_ERR_INC(NetUDP_ErrRxHdrDataLenCtr); *perr = NET_UDP_ERR_INVALID_LEN_DATA; return; } #endif udp_data_len = udp_tot_len - pbuf_hdr->TCP_UDP_HdrLen; pbuf_hdr->TCP_UDP_DataLen = udp_data_len; pbuf_hdr->DataLen -= (NET_BUF_SIZE) pbuf_hdr->TCP_UDP_HdrLen; pbuf_hdr->DataIx = (CPU_INT16U )(pbuf_hdr->TCP_UDP_HdrDataIx + pbuf_hdr->TCP_UDP_HdrLen); pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_APP; pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr; while (pbuf_next != (NET_BUF *)0) { /* Calc ALL pkt bufs' data len/ix (see Note #5b). */ pbuf_next_hdr = &pbuf_next->Hdr; pbuf_next_hdr->DataIx = pbuf_next_hdr->TCP_UDP_HdrDataIx; pbuf_next_hdr->TCP_UDP_HdrLen = 0; /* NULL UDP hdr len in each pkt buf. */ pbuf_next_hdr->TCP_UDP_TotLen = udp_tot_len; /* Dup UDP tot len & ... */ pbuf_next_hdr->TCP_UDP_DataLen = udp_data_len; /* ... data len in each pkt buf (see Note #5c). */ pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_APP; pbuf_next = (NET_BUF *)pbuf_next_hdr->NextBufPtr; } *perr = NET_UDP_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_RxPktDemuxDatagram() * * Description : Demultiplex UDP datagram to appropriate socket or application connection. * * Argument(s) : pbuf Pointer to network buffer that received UDP datagram. * ---- Argument checked in NetUDP_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_RX Receive error; packet discarded. * NET_ERR_RX_DEST Invalid destination; no connection available * for received packet. * * -------- RETURNED BY NetSock_Rx() : -------- * NET_SOCK_ERR_NONE UDP datagram successfully received to * socket connection. * * - RETURNED BY NetUDP_RxPktDemuxAppData() : - * NET_APP_ERR_NONE UDP datagram successfully received to * application connection. * * Return(s) : none. * * Caller(s) : NetUDP_Rx(). * * Note(s) : (1) (a) Attempt demultiplex of received UDP datagram to socket connections first, if enabled. * * (b) On any error, attempt demultiplex to application connections, if enabled. * * (2) When network buffer is demultiplexed to socket or application receive, the buffer's reference * counter is NOT incremented since the UDP layer does NOT maintain a reference to the buffer. ********************************************************************************************************* */ static void NetUDP_RxPktDemuxDatagram (NET_BUF *pbuf, NET_ERR *perr) { #if ((NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_APP ) || \ (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK_APP)) CPU_BOOLEAN rx_demux_app; #endif #if ((NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK ) || \ (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK_APP)) /* If socks en'd, ... */ NetSock_Rx(pbuf, perr); /* ... attempt sock demux (see Note #1a). */ #endif #if (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_APP) rx_demux_app = DEF_YES; #elif (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK_APP) switch (*perr) { case NET_SOCK_ERR_NONE: rx_demux_app = DEF_NO; break; case NET_ERR_RX_DEST: rx_demux_app = DEF_YES; break; case NET_ERR_INIT_INCOMPLETE: case NET_ERR_RX: default: return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif #if ((NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_APP ) || \ (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK_APP)) /* If socks dis'd OR sock demux fails, ... */ if (rx_demux_app == DEF_YES) { NetUDP_RxPktDemuxAppData(pbuf, perr); /* ... attempt app demux (see Note #1b). */ } #endif } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_RxPktDemuxAppData() * * Description : Prepare UDP packet for application-specific UDP connection handler function. * * Argument(s) : pbuf Pointer to network buffer that received UDP datagram. * ---- Argument checked in NetUDP_Rx(). * * perr Pointer to variable that will receive the return error code from this function * (see Note #1b) : * * -- RETURNED BY NetUDP_RxAppDataHandler() : --- * NET_APP_ERR_NONE UDP datagram successfully received to * application connection. * NET_ERR_RX Receive error; packet discarded. * NET_ERR_RX_DEST Invalid destination; no application connection * available for received packet. * * Return(s) : none. * * Caller(s) : NetUDP_RxPktDemuxDatagram(). * * Note(s) : (1) Application-specific UDP connection handler function is fully responsible for properly * receiving, demultiplexing, & handling all UDP receive packets to the appropriate * application connections. * * (a) (1) (A) (1) If the application-specific UDP connection handler function successfully * demultiplexes UDP receive packets to an application connection, the handler * function MUST at some point call NetUDP_RxAppData() to deframe the application * data from the packet buffer(s) into an application array as well as copy any * received IP options into an application IP options buffer. * * (a) The application-specific connection handler function may service the * application data immediately within the handler function, in which case * the application data SHOULD be serviced as quickly as possible since the * network's global lock remains acquired for the full duration of the * network receive. Thus, no other network receives or transmits can occur * while the application-specific handler function executes. * * (b) The application-specific connection handler function may delay servicing * the application data by some other application-specific data servicing * function(s), in which case the servicing function(s) MUST : * * (1) Acquire the network's global lock PRIOR to calling NetUDP_RxAppData() * (2) Release the network's global lock AFTER calling NetUDP_RxAppData() * * See 'NetUDP_RxAppData() Note #2'. * * (2) (a) If application-specific handler function calls NetUDP_RxAppData() for a * specific UDP receive packet, the handler function MUST NOT free the UDP * packet's network buffer(s), since NetUDP_RxAppData() frees the network * buffer(s) [see 'NetUDP_RxAppData() Note #1f']. * * (b) If application-specific handler function does NOT call NetUDP_RxAppData() * for a specific UDP receive packet, the handler function SHOULD call * NetUDP_RxPktDiscard() to free the packet network buffer(s). * * (3) FAILURE to call NetUDP_RxAppData() or NetUDP_RxPktDiscard() MAY result in * lost network buffer(s). * * (B) Application-specific handler function MUST return 'NET_APP_ERR_NONE' error code * following the successful demultiplexing of UDP receive packet(s) to application * connection(s), regardless of whether the handler function serviced the application * data. * * (2) If the application-specific UDP connection handler function fails to demultiplex or * handle UDP receive packets, the handler function MUST return one of the following * error codes : * * (A) 'NET_ERR_RX_DEST' for any received UDP packets NOT destined to an available * application connection. * * (B) 'NET_ERR_RX' for any other receive error. * * (b) Application-specific UDP connection handler function MUST return one of the following * error codes ONLY [see 'Argument(s) : perr'] : * * NET_APP_ERR_NONE See Note #1a1B * NET_ERR_RX See Note #1a2B * NET_ERR_RX_DEST See Note #1a2A ********************************************************************************************************* */ /*$PAGE*/ #if ((NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_APP ) || \ (NET_UDP_CFG_APP_API_SEL == NET_UDP_APP_API_SEL_SOCK_APP)) static void NetUDP_RxPktDemuxAppData (NET_BUF *pbuf, NET_ERR *perr) { NET_BUF_HDR *pbuf_hdr; NET_IP_ADDR src_addr; NET_IP_ADDR dest_addr; NET_UDP_PORT_NBR src_port; NET_UDP_PORT_NBR dest_port; pbuf_hdr = &pbuf->Hdr; src_addr = (NET_IP_ADDR )pbuf_hdr->IP_AddrSrc; src_port = (NET_UDP_PORT_NBR)pbuf_hdr->TCP_UDP_PortSrc; dest_addr = (NET_IP_ADDR )pbuf_hdr->IP_AddrDest; dest_port = (NET_UDP_PORT_NBR)pbuf_hdr->TCP_UDP_PortDest; NetUDP_RxAppDataHandler(pbuf, src_addr, src_port, dest_addr, dest_port, perr); } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_RxPktFree() * * Description : Free network buffer(s). * * Argument(s) : pbuf Pointer to network buffer. * * Return(s) : none. * * Caller(s) : NetUDP_RxAppData(). * * Note(s) : none. ********************************************************************************************************* */ static void NetUDP_RxPktFree (NET_BUF *pbuf) { NetBuf_FreeBufList((NET_BUF *)pbuf, (NET_CTR *)0); } /* ********************************************************************************************************* * NetUDP_RxPktDiscard() * * Description : On any UDP Receive errors, discard UDP 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) : NetUDP_Rx(), * NetUDP_RxAppData(). * * Note(s) : none. ********************************************************************************************************* */ static void NetUDP_RxPktDiscard (NET_BUF *pbuf, NET_ERR *perr) { NET_CTR *pctr; #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) pctr = (NET_CTR *)&NetUDP_ErrRxPktDiscardedCtr; #else pctr = (NET_CTR *) 0; #endif NetBuf_FreeBufList((NET_BUF *)pbuf, (NET_CTR *)pctr); *perr = NET_ERR_RX; } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_Tx() * * Description : (1) Prepare & transmit packets from application layer(s) to IP layer : * * (a) Validate transmit packet * (b) Prepare UDP datagram header * (c) Transmit UDP packet * (d) Update transmit statistics * * * Argument(s) : pbuf Pointer to network buffer to transmit UDP packet. * ---- Argument validated in NetUDP_TxAppData(). * * src_addr Source IP address. * * src_port Source UDP port. * * dest_addr Destination IP address. * * dest_port Destination UDP port. * * TOS Specific TOS to transmit UDP/IP packet * (see 'net_ip.h IP HEADER TYPE OF SERVICE (TOS) DEFINES'). * * TTL Specific TTL to transmit UDP/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_udp Flags to select UDP transmit options (see Note #2); bit-field flags logically OR'd : * * NET_UDP_FLAG_NONE No UDP transmit flags selected. * NET_UDP_FLAG_TX_CHK_SUM_DIS DISABLE transmit check-sums. * NET_UDP_FLAG_TX_BLOCK Transmit UDP application data with blocking, * if flag set; without blocking, if clear * (see Note #2a). * * flags_ip Flags to select IP 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_ip 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_UDP_ERR_NONE UDP datagram(s) successfully prepared & * transmitted to IP layer. * * -- RETURNED BY NetUDP_TxPktValidate() : -- * NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type. * NET_BUF_ERR_INVALID_IX Invalid or insufficient buffer index. * NET_UDP_ERR_INVALID_LEN_DATA Invalid protocol/data length. * NET_UDP_ERR_INVALID_PORT_NBR Invalid UDP port number. * NET_UDP_ERR_INVALID_FLAG Invalid UDP flag(s). * * - RETURNED BY NetUDP_TxPktPrepareHdr() : - * NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer. * NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size. * NET_UTIL_ERR_INVALID_PROTOCOL Invalid data packet protocol. * * -------- RETURNED BY NetIP_Tx() : -------- * NET_ERR_INIT_INCOMPLETE Network initialization NOT complete. * NET_ERR_TX Transmit error; packet(s) discarded. * Return(s) : none. * * Caller(s) : NetUDP_TxAppData(). * * Note(s) : (2) #### Some UDP transmit flag options NOT yet implemented : * * (a) NET_UDP_FLAG_TX_BLOCK * * See also 'NetUDP_TxPktValidate() Note #2b'. * * (3) Network buffer already freed by lower layer; only increment error counter. ********************************************************************************************************* */ /*$PAGE*/ static void NetUDP_Tx (NET_BUF *pbuf, NET_IP_ADDR src_addr, NET_UDP_PORT_NBR src_port, NET_IP_ADDR dest_addr, NET_UDP_PORT_NBR dest_port, NET_IP_TOS TOS, NET_IP_TTL TTL, CPU_INT16U flags_udp, CPU_INT16U flags_ip, void *popts_ip, 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; /* --------------- VALIDATE TX UDP PKT ---------------- */ pbuf_hdr = &pbuf->Hdr; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetUDP_TxPktValidate(pbuf, pbuf_hdr, src_port, dest_port, flags_udp, perr); switch (*perr) { case NET_UDP_ERR_NONE: break; case NET_ERR_INVALID_PROTOCOL: case NET_BUF_ERR_INVALID_IX: case NET_UDP_ERR_INVALID_LEN_DATA: case NET_UDP_ERR_INVALID_PORT_NBR: case NET_UDP_ERR_INVALID_FLAG: default: NetUDP_TxPktDiscard(pbuf); return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif /*$PAGE*/ /* ------------------ PREPARE UDP HDR ----------------- */ NetUDP_TxPktPrepareHdr(pbuf, pbuf_hdr, src_addr, src_port, dest_addr, dest_port, flags_udp, perr); /* -------------------- TX UDP PKT -------------------- */ switch (*perr) { case NET_UDP_ERR_NONE: NetIP_Tx(pbuf, src_addr, dest_addr, TOS, TTL, flags_ip, popts_ip, perr); break; case NET_UTIL_ERR_NULL_PTR: case NET_UTIL_ERR_NULL_SIZE: case NET_UTIL_ERR_INVALID_PROTOCOL: case NET_BUF_ERR_INVALID_IX: default: NetUDP_TxPktDiscard(pbuf); return; /* Prevent 'break NOT reachable' compiler warning. */ } /* ----------------- UPDATE TX STATS ------------------ */ switch (*perr) { /* Chk err from NetIP_Tx(). */ case NET_IP_ERR_NONE: NET_CTR_STAT_INC(NetUDP_StatTxDatagramCtr); *perr = NET_UDP_ERR_NONE; break; case NET_ERR_INIT_INCOMPLETE: case NET_ERR_TX: NET_CTR_ERR_INC(NetUDP_ErrTxPktDiscardedCtr); /* See Note #2. */ return; /* Prevent 'break NOT reachable' compiler warning. */ default: NetUDP_TxPktDiscard(pbuf); return; /* Prevent 'break NOT reachable' compiler warning. */ } } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_TxPktValidate() * * Description : (1) Validate UDP transmit packet parameters & options : * * (a) Packets with the following invalid parameters will be "silently discarded" : * * (1) Protocols other than supported protocols : * (A) Application * (B) BSD Sockets * * (2) Data Length * (3) Source Port * (4) Destination Port * (5) Flags * * * Argument(s) : pbuf Pointer to network buffer to transmit UDP packet. * ---- Argument checked in NetUDP_Tx(). * * pbuf_hdr Pointer to network buffer header. * -------- Argument validated in NetUDP_Tx(). * * src_port Source UDP port. * * dest_port Destination UDP port. * * flags_udp Flags to select UDP transmit options (see Note #2); bit-field flags logically OR'd : * * NET_UDP_FLAG_NONE No UDP transmit flags selected. * NET_UDP_FLAG_TX_CHK_SUM_DIS DISABLE transmit check-sums. * NET_UDP_FLAG_TX_BLOCK Transmit UDP application data with blocking, * if flag set; without blocking, if clear * (see Note #2b1). * * perr Pointer to variable that will receive the return error code from this function : * * NET_UDP_ERR_NONE Transmit packet validated. * NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type. * NET_BUF_ERR_INVALID_IX Invalid or insufficient buffer index. * NET_UDP_ERR_INVALID_LEN_DATA Invalid protocol/data length. * NET_UDP_ERR_INVALID_PORT_NBR Invalid UDP port number. * NET_UDP_ERR_INVALID_FLAG Invalid UDP flag(s). * * Return(s) : none. * * Caller(s) : NetUDP_Tx(). * * Note(s) : (2) (a) #### Only some UDP transmit flag options are implemented. If other flag options * are requested, NetUDP_Tx() handler function(s) abort & return appropriate error * codes so that requested flag options are NOT silently ignored. * * (b) #### Some UDP transmit flag options NOT yet implemented : * * (1) NET_UDP_FLAG_TX_BLOCK ********************************************************************************************************* */ /*$PAGE*/ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetUDP_TxPktValidate (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_UDP_PORT_NBR src_port, NET_UDP_PORT_NBR dest_port, CPU_INT16U flags_udp, 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; /* ----------------- VALIDATE PROTOCOL ---------------- */ switch (pbuf_hdr->ProtocolHdrType) { case NET_PROTOCOL_TYPE_APP: case NET_PROTOCOL_TYPE_SOCK: case NET_PROTOCOL_TYPE_UDP: ix = (CPU_INT16U)pbuf_hdr->DataIx; len = (CPU_INT16U)pbuf_hdr->DataLen; break; case NET_PROTOCOL_TYPE_NONE: default: NET_CTR_ERR_INC(NetUDP_ErrTxProtocolCtr); *perr = NET_ERR_INVALID_PROTOCOL; return; /* Prevent 'break NOT reachable' compiler warning. */ } if (ix == NET_BUF_IX_NONE) { NET_CTR_ERR_INC(NetUDP_ErrTxInvalidBufIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } if (ix < NET_UDP_HDR_SIZE) { NET_CTR_ERR_INC(NetUDP_ErrTxInvalidBufIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } /* -------------- VALIDATE TOT DATA LEN --------------- */ if (len != pbuf_hdr->TotLen) { NET_CTR_ERR_INC(NetUDP_ErrTxHdrDataLenCtr); *perr = NET_UDP_ERR_INVALID_LEN_DATA; return; } /* ---------------- VALIDATE UDP PORTS ---------------- */ if (src_port == NET_UDP_PORT_NBR_RESERVED) { NET_CTR_ERR_INC(NetUDP_ErrTxHdrPortSrcCtr); *perr = NET_UDP_ERR_INVALID_PORT_NBR; return; } if (dest_port == NET_UDP_PORT_NBR_RESERVED) { NET_CTR_ERR_INC(NetUDP_ErrTxHdrPortDestCtr); *perr = NET_UDP_ERR_INVALID_PORT_NBR; return; } /* ---------------- VALIDATE UDP FLAGS ---------------- */ flag_mask = NET_UDP_FLAG_NONE | NET_UDP_FLAG_TX_CHK_SUM_DIS | NET_UDP_FLAG_TX_BLOCK; /* See Note #2b1. */ if ((flags_udp & ~flag_mask) != NET_UDP_FLAG_NONE) { /* If any invalid flags req'd, rtn err (see Note #2a). */ NET_CTR_ERR_INC(NetUDP_ErrTxHdrFlagsCtr); *perr = NET_UDP_ERR_INVALID_FLAG; return; } *perr = NET_UDP_ERR_NONE; } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_TxPktPrepareHdr() * * Description : (1) Prepare UDP header : * * (a) Update network buffer's protocol index & length controls. * * (b) Prepare the transmit packet's following UDP header fields : * * (1) Source Port * (2) Destination Port * (3) Datagram Length * (4) Check-Sum See Note #3 * * (c) Convert the following UDP header fields from host-order to network-order : * * (1) Source Port * (2) Destination Port * (3) Datagram Length * (4) Check-Sum See Note #3g * * * Argument(s) : pbuf Pointer to network buffer to transmit UDP packet. * ---- Argument checked in NetUDP_Tx(). * * pbuf_hdr Pointer to network buffer header. * -------- Argument validated in NetUDP_Tx(). * * src_addr Source IP address. * * src_port Source UDP port. * -------- Argument validated in NetUDP_TxPktValidate(). * * dest_addr Destination IP address. * * dest_port Destination UDP port. * --------- Argument validated in NetUDP_TxPktValidate(). * * flags_udp Flags to select UDP transmit options (see Note #2); bit-field flags logically OR'd : * --------- * NET_UDP_FLAG_NONE No UDP transmit flags selected. * NET_UDP_FLAG_TX_CHK_SUM_DIS DISABLE transmit check-sums. * NET_UDP_FLAG_TX_BLOCK Transmit UDP application data with blocking, * if flag set; without blocking, if clear * (see Note #2a). * * Argument checked in NetUDP_TxPktValidate(). * * perr Pointer to variable that will receive the return error code from this function : * * NET_UDP_ERR_NONE UDP header successfully prepared. * * - RETURNED BY NetUtil_16BitOnesCplChkSumDataCalc() : - * NET_UTIL_ERR_NULL_PTR Check-sum passed a NULL pointer. * NET_UTIL_ERR_NULL_SIZE Check-sum passed a zero size. * NET_UTIL_ERR_INVALID_PROTOCOL Invalid data packet protocol. * NET_BUF_ERR_INVALID_IX Invalid buffer index. * * Return(s) : none. * * Caller(s) : NetUDP_Tx(). *$PAGE* * Note(s) : (2) #### Some UDP transmit flag options NOT yet implemented : * * (a) NET_UDP_FLAG_TX_BLOCK * * See also 'NetUDP_TxPktValidate() Note #2b'. * * (3) (a) UDP header Check-Sum MUST be calculated AFTER the entire UDP 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) "An application MAY optionally be able to control whether a UDP checksum will be * be generated" (see RFC #1122, Section 4.1.3.4). * * (c) Although neither RFC #768 nor RFC #1122, Sections 4.1 expressly specifies, it is * assumed that that the UDP header Check-Sum field MUST be cleared to '0' BEFORE the * UDP header Check-Sum is calculated. * * See also 'net_ip.c NetIP_TxPktPrepareHdr() Note #6b', * 'net_icmp.c NetICMP_TxMsgErr() Note #7b', * 'net_icmp.c NetICMP_TxMsgReq() Note #7b', * 'net_icmp.c NetICMP_TxMsgReply() Note #5b', * 'net_tcp.c NetTCP_TxPktPrepareHdr() Note #3b'. * * (d) (1) In addition to the UDP datagram header & data, the UDP Check-Sum calculation * includes "a pseudo header of information from the IP header ... conceptually * prefixed to the UDP header [which] contains the source address, the destination * address, the protocol, and the UDP length" (see RFC #768, Section 'Fields : * Checksum'). * * (2) Since network check-sum functions REQUIRE that 16-bit one's-complement check- * sum calculations be performed on headers & data arranged in network-order (see * 'net_util.c NetUtil_16BitOnesCplChkSumDataCalc() Note #3'), UDP pseudo-header * values MUST be set or converted to network-order. * * (e) RFC #768, Section 'Fields : Checksum' specifies that "the data [is] padded with zero * octets at the end (if necessary) to make a multiple of two octets". * * See also 'net_util.c NetUtil_16BitSumDataCalc() Note #8'. * * (f) "If the computed checksum is zero" (i.e. one's-complement positive zero -- all * bits equal to zero), then "it is transmitted as all ones (the equivalent in * one's complement arithmetic" (i.e. one's-complement negative zero -- all bits * equal to one) [RFC #768, Section 'Fields : Checksum']. * * (g) The UDP header Check-Sum field is returned in network-order & MUST NOT be re- * converted back to host-order (see 'net_util.c NetUtil_16BitOnesCplChkSumDataCalc() * Note #4'). ********************************************************************************************************* */ /*$PAGE*/ static void NetUDP_TxPktPrepareHdr (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_IP_ADDR src_addr, NET_UDP_PORT_NBR src_port, NET_IP_ADDR dest_addr, NET_UDP_PORT_NBR dest_port, CPU_INT16U flags_udp, NET_ERR *perr) { NET_UDP_HDR *pudp_hdr; NET_UDP_PSEUDO_HDR udp_pseudo_hdr; NET_CHK_SUM udp_chk_sum; CPU_BOOLEAN tx_chk_sum; /* ----------------- UPDATE BUF CTRLS ----------------- */ pbuf_hdr->TCP_UDP_HdrLen = NET_UDP_HDR_SIZE; pbuf_hdr->TCP_UDP_HdrDataIx = pbuf_hdr->DataIx - pbuf_hdr->TCP_UDP_HdrLen; pbuf_hdr->TotLen += (NET_BUF_SIZE)pbuf_hdr->TCP_UDP_HdrLen; pbuf_hdr->TCP_UDP_TotLen = (CPU_INT16U )pbuf_hdr->TotLen; pbuf_hdr->TCP_UDP_DataLen = (CPU_INT16U )pbuf_hdr->DataLen; pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_UDP; /* ----------------- PREPARE UDP HDR ------------------ */ pudp_hdr = (NET_UDP_HDR *)&pbuf->Data[pbuf_hdr->TCP_UDP_HdrDataIx]; /* ---------------- PREPARE UDP PORTS ----------------- */ NET_UTIL_VAL_COPY_SET_NET_16(&pudp_hdr->PortSrc, &src_port); NET_UTIL_VAL_COPY_SET_NET_16(&pudp_hdr->PortDest, &dest_port); /* ------------- PREPARE UDP DATAGRAM LEN ------------- */ NET_UTIL_VAL_COPY_SET_NET_16(&pudp_hdr->DatagramLen, &pbuf_hdr->TCP_UDP_TotLen); /* --------------- PREPARE UDP CHK SUM ---------------- */ #if (NET_UDP_CFG_TX_CHK_SUM_EN == DEF_ENABLED) tx_chk_sum = DEF_BIT_IS_CLR(flags_udp, NET_UDP_FLAG_TX_CHK_SUM_DIS); #else tx_chk_sum = DEF_NO; #endif if (tx_chk_sum == DEF_YES) { /* If en'd (see Note #3b), prepare UDP tx chk sum. */ NET_UTIL_VAL_SET_NET_16(&pudp_hdr->ChkSum, 0x0000); /* Clr UDP chk sum (see Note #3c). */ /* Cfg UDP chk sum pseudo-hdr (see Note #3d). */ udp_pseudo_hdr.AddrSrc = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(src_addr); udp_pseudo_hdr.AddrDest = (NET_IP_ADDR)NET_UTIL_HOST_TO_NET_32(dest_addr); udp_pseudo_hdr.Zero = (CPU_INT08U )0x00; udp_pseudo_hdr.Protocol = (CPU_INT08U )NET_IP_HDR_PROTOCOL_UDP; udp_pseudo_hdr.DatagramLen = (CPU_INT16U )NET_UTIL_HOST_TO_NET_16(pbuf_hdr->TCP_UDP_TotLen); /* Calc UDP chk sum. */ udp_chk_sum = NetUtil_16BitOnesCplChkSumDataCalc((void *) pbuf, (void *)&udp_pseudo_hdr, (CPU_INT16U) NET_UDP_PSEUDO_HDR_SIZE, (NET_ERR *) perr); if (*perr != NET_UTIL_ERR_NONE) { return; } if (udp_chk_sum == NET_UDP_HDR_CHK_SUM_POS_ZERO) { /* If equal to one's-cpl pos zero, ... */ udp_chk_sum = NET_UDP_HDR_CHK_SUM_NEG_ZERO; /* ... set to one's-cpl neg zero (see Note #3f). */ } } else { /* Else tx NO chk sum. */ udp_chk_sum = NET_UTIL_HOST_TO_NET_16(NET_UDP_HDR_CHK_SUM_NONE); } NET_UTIL_VAL_COPY_16(&pudp_hdr->ChkSum, &udp_chk_sum); /* Copy UDP chk sum in net order (see Note #3g). */ *perr = NET_UDP_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetUDP_TxPktFree() * * Description : Free network buffer. * * Argument(s) : pbuf Pointer to network buffer. * * Return(s) : none. * * Caller(s) : NetUDP_Tx(), * NetUDP_TxAppData(). * * Note(s) : (1) (a) Although UDP Transmit initially requests the network buffer for transmit, * the UDP layer does NOT maintain a reference to the buffer. * * (b) Also, since the network interface layer frees ALL unreferenced buffers * after successful transmission [see 'net_if_pkt.c NetIF_Pkt_TxPktFree()' * or 'net_if_char.c NetIF_Char_TxPktFree()'], the UDP layer MUST not * free the transmit buffer. ********************************************************************************************************* */ static void NetUDP_TxPktFree (NET_BUF *pbuf) { (void)&pbuf; /* Prevent compiler warning (see Note #1). */ } /* ********************************************************************************************************* * NetUDP_TxPktDiscard() * * Description : On any Transmit packet errors, discard packet & buffer. * * Argument(s) : pbuf Pointer to network buffer. * * Return(s) : none. * * Caller(s) : NetUDP_Tx(), * NetUDP_TxAppData(). * * Note(s) : none. ********************************************************************************************************* */ static void NetUDP_TxPktDiscard (NET_BUF *pbuf) { NET_CTR *pctr; #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) pctr = (NET_CTR *)&NetUDP_ErrTxPktDiscardedCtr; #else pctr = (NET_CTR *) 0; #endif NetBuf_FreeBuf((NET_BUF *)pbuf, (NET_CTR *)pctr); }