Files
m241Neelima/components/ip_net2-6.9/iplite2/src/iplite_udp.c
T
2026-07-30 11:19:44 +05:30

333 lines
9.7 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: iplite_udp.c,v $ $Revision: 1.23 $
* $Source: /home/interpeak/CVSRoot/iplite2/src/iplite_udp.c,v $
* $Author: hxie $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/* User datagram protocol transport layer */
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "iplite_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#if !defined(IPLITE_ONE_FILE) || defined(IPLITE_C)
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_inet.h>
#include "iplite_h.h"
#include "iplite_sock.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iplite_udp_input
*===========================================================================
* Description: Input handler for packet to UDP sockets. This function will
* NOT free the packet if the operation fails.
* Parameters: pkt - The received packet.
* is_multicast - Set to IP_TRUE if the packet was sent to a
* multicast address.
* proto - The protocol number.
* src_addr - The address (Ipv4 or IPv6) of the sender.
* dst_addr - The address (Ipv4 or IPv6) of the receiver (this system).
* socklookup - A pointer to a function that can return the socket
* that is associated with this packet.
* Returns: 0 >= number of matching sockets, <0 = error code
*
*/
IP_GLOBAL int
iplite_udp_input(Ipcom_pkt *pkt, Ip_bool is_multicast,
IP_CONST void* src_addr, IP_CONST void* dst_addr,
Iplite_socklookup socklookup)
{
Iplite_pkt_udp *udp_hdr;
int retval;
Ip_u16 ulen_h;
Iplite_socket *sock;
Ip_u16 src_port;
Ip_u16 dst_port;
int next;
IPLITE_STATS(udp_input++);
IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_UDP_INPUT);
if (pkt->end - pkt->start < IPLITE_UDP_HDR_SIZE)
{
IPLITE_STATS(udp_input_hdr_trunc++);
IPCOM_MIB2(udpInErrors++);
return -IP_ERRNO_EINVAL;
}
udp_hdr = (Iplite_pkt_udp*) &pkt->data[pkt->start];
ulen_h = ip_ntohs(udp_hdr->ulen);
src_port = ip_ntohs(udp_hdr->sport);
dst_port = ip_ntohs(udp_hdr->dport);
if (pkt->end - pkt->start < ulen_h)
{
IPLITE_STATS(udp_input_hdr_trunc++);
IPCOM_MIB2(udpInErrors++);
return -IP_ERRNO_EINVAL;
}
pkt->end = pkt->start + (int)ulen_h;
if (udp_hdr->sum != 0)
{
pkt->chk += ipcom_in_checksum_update(&pkt->data[pkt->start],
(Ip_size_t) ulen_h);
if (ipcom_in_checksum_finish(pkt->chk) != 0)
{
/* Wrong checksum */
IPLITE_STATS(udp_input_badchksum++);
IPCOM_MIB2(udpInErrors++);
return -IP_ERRNO_EINVAL;
}
}
/* Move the start to beginning of application data */
pkt->start += IPLITE_UDP_HDR_SIZE;
if (is_multicast)
{
IPLITE_STATS(udp_input_multicast++);
retval = iplite_raw_input(pkt, IP_FALSE, IP_IPPROTO_UDP,
src_addr, src_port, dst_addr, dst_port, socklookup);
if (retval >= 0)
{
/* The packet must be freed unlesss an error occured */
ipcom_pkt_free(pkt);
IPCOM_MIB2(udpInDatagrams++);
}
else
{
IPCOM_MIB2(udpInErrors++);
}
return retval;
}
/* Lookup UDP socket. Honor the SO_BINDTODEVICE option. */
next = 0;
do
{
sock = socklookup(IP_IPPROTO_UDP, dst_addr, dst_port, src_addr, src_port, &next);
} while (sock != IP_NULL
&& sock->bind_to_ifindex != 0
&& sock->bind_to_ifindex != pkt->ifindex);
if (sock != IP_NULL)
{
IPLITE_STATS(udp_input_sock_match++);
pkt->fd = sock->ipcom.fd;
retval = iplite_queue_received_packet(pkt, sock);
if (sock->ipcom.event_cb)
sock->ipcom.event_cb((Ipcom_socket *)sock, pkt, IP_SOEVENT_CB_SELREAD);
if (retval < 0)
{
IPLITE_STATS(udp_input_queue_pkt_err++);
IPCOM_MIB2(udpInErrors++);
return retval;
}
else
{
IPLITE_STATS(udp_input_queue_pkt_ok++);
}
IPCOM_MIB2(udpInDatagrams++);
return 1;
}
else
{
IPLITE_STATS(udp_input_sock_nomatch++);
IPCOM_MIB2(udpNoPorts++);
}
IPLITE_STATS(udp_input_econnrefused++);
return -IP_ERRNO_ECONNREFUSED;
}
/*
*===========================================================================
* iplite_udp_output
*===========================================================================
* Description: Adds a UDP header to the application data.
* Parameters: sock - The socket to use when sending.
* to - The destination address address, ignored if the socket
* is in connected state.
* pkt - The packet data to send.
* Returns: >0 = application bytes sent, <0 = error code.
*
*/
IP_GLOBAL int
iplite_udp_output(Iplite_socket *sock, IP_CONST struct Ip_sockaddr *to, Ipcom_pkt *pkt)
{
Ip_u16 to_port_n;
Iplite_pkt_udp *udp;
int ret;
IPLITE_STATS(udp_output++);
ip_assert(sock->ipcom.type == IP_SOCK_DGRAM);
ip_assert(sock->proto == IP_IPPROTO_UDP);
if (IP_BIT_ISSET(sock->flags, IPLITE_SOCKET_FLAG_CONNECTED))
to_port_n = ip_htons(sock->dport);
else if (to == IP_NULL)
{
/* No destination address */
ret = -IP_ERRNO_EDESTADDRREQ;
goto errout;
}
else
/* Ok for both IPv4 and IPv6 */
to_port_n = ((struct Ip_sockaddr_in*) to)->sin_port;
if (pkt->start < IPLITE_UDP_HDR_SIZE)
{
/* Not enough space for UDP header */
IPLITE_STATS(udp_output_hdr_trunc++);
ret = -IP_ERRNO_EFAULT;
goto errout;
}
/* Fill in UDP header. */
pkt->start -= IPLITE_UDP_HDR_SIZE;
udp = (Iplite_pkt_udp *)&pkt->data[pkt->start];
udp->sport = ip_htons(sock->sport);
ip_assert(udp->sport != 0);
udp->dport = to_port_n;
udp->sum = 0;
udp->ulen = (Ip_u16) ip_htons(pkt->end - pkt->start);
if (IP_BIT_ISSET(sock->flags, IPLITE_SOCKET_FLAG_ADDCHECKSUM))
{
/* Update the checksum with the UDP header */
pkt->chk += (Ip_u32)udp->sport;
pkt->chk += (Ip_u32)udp->dport;
pkt->chk += (Ip_u32)udp->ulen;
/* note: ignore sum entry since 0! */
}
switch(sock->ipcom.domain)
{
#ifdef IPCOM_USE_INET
case IP_AF_INET:
IPCOM_MIB2(udpOutDatagrams++);
return iplite_ip4_sendto(sock, to, pkt);
#endif
#ifdef IPCOM_USE_INET6
case IP_AF_INET6:
IPCOM_MIB2(udpOutDatagrams++);
return iplite_ip6_sendto(sock, to, pkt);
#endif
default:
/* Invalid domain */
IP_PANIC();
IPLITE_STATS(udp_output_eafnosupport++);
ret = -IP_ERRNO_EAFNOSUPPORT;
break;
}
errout:
ipcom_pkt_free(pkt);
return ret;
}
#endif /* !defined(IPLITE_ONE_FILE) || defined(IPLITE_C) */
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/