2112 lines
99 KiB
C
Raw Blame History

This file contains invisible Unicode characters

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

/*
*********************************************************************************************************
* uC/TCP-IP
* The Embedded TCP/IP Suite
*
* (c) Copyright 2003-2007; Micrium, Inc.; Weston, FL
*
* All rights reserved. Protected by international copyright laws.
*
* uC/TCP-IP is provided in source form for FREE evaluation, for educational
* use or peaceful research. If you plan on using uC/TCP-IP in a commercial
* product you need to contact Micrium to properly license its use in your
* product. We provide ALL the source code for your convenience and to help
* you experience uC/TCP-IP. The fact that the source code is provided does
* NOT mean that you can use it without paying a licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the Embedded community with the finest
* software available. Your honesty is greatly appreciated.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* NETWORK 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 <net.h>
/*$PAGE*/
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/*$PAGE*/
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
/* --------------- RX FNCTS --------------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void 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);
}