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

444 lines
14 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: iplite_raw.c,v $ $Revision: 1.31 $
* $Source: /home/interpeak/CVSRoot/iplite2/src/iplite_raw.c,v $
* $Author: hxie $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/* Raw socket address family functions */
/*
****************************************************************************
* 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 <ipcom_syslog.h>
#include "iplite_h.h"
#include "iplite_sock.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iplite_packet_socklookup
*===========================================================================
* Description: Returns IP_AF_PACKET sockets that match the frame type.
* Parameters: frame_type - The frame type that the matching socket must have.
* unused1 -
* unused2 -
* unused3 -
* unused4 -
* next - [in] The first socket to look at. [out] the next socket
* to look at. Can be IP_NULL if only the first match should be
* returned.
* Returns: >0 = application bytes sent, <0 = error code.
*
*/
#ifdef IPCOM_USE_PACKET
IP_STATIC Iplite_socket *
iplite_packet_socklookup(int frame_type, IP_CONST void *unused1, Ip_u16 unused2,
IP_CONST void *unused3, Ip_u16 unused4, int *next)
{
int i;
Iplite_socket *sock;
(void)unused1;
(void)unused2;
(void)unused3;
(void)unused4;
for (i = (next == IP_NULL ? 0 : *next); i < IPLITE_CONF_MAX_SOCKETS; i++)
{
sock = iplite.sockets[i];
if (sock == IP_NULL)
continue;
if (sock->ipcom.domain != IP_AF_PACKET)
continue;
if (sock->proto != 0 && sock->proto != frame_type)
continue;
if (next != IP_NULL)
*next = i + 1;
return sock;
}
return IP_NULL;
}
#endif /* IPCOM_USE_PACKET */
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
#ifdef IPCOM_USE_PACKET
/*
*===========================================================================
* iplite_packet_output
*===========================================================================
* Description: Sends a raw frame directly to the driver (IP_SOCK_RAW) or
* directly to the link layer to get a link header
* (IP_SOCK_DGRAM) (but no ARP or simlilar is performed).
* 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_packet_output(Iplite_socket *sock, IP_CONST struct Ip_sockaddr *to, Ipcom_pkt *pkt)
{
struct Ip_sockaddr_ll *ll_addr = (struct Ip_sockaddr_ll *) to;
Iplite_netif *netif;
int ret;
int max_pkt_len;
if (ll_addr->sll_family != IP_AF_PACKET)
{
IPCOM_LOG2(DEBUG2, "RAW: sll_family must be IP_AF_PACKET (%d), got %d",
IP_AF_PACKET, (int)ll_addr->sll_family);
return -IP_ERRNO_EPROTOTYPE;
}
netif = iplite_if_indextonetif(ll_addr->sll_ifindex);
if (netif == IP_NULL)
{
IPCOM_LOG1(DEBUG2, "RAW: %d is not a valid interface index",
(int)ll_addr->sll_ifindex);
return -IP_ERRNO_ENXIO;
}
pkt->ifindex = netif->ipcom.ifindex;
if (sock->ipcom.type == IP_SOCK_RAW)
/* Link layer header included */
max_pkt_len = netif->ipcom.mtu + netif->ipcom.link_hdr_size;
else if (sock->ipcom.type == IP_SOCK_DGRAM)
/* Link layer must be added by the stack */
max_pkt_len = netif->ipcom.mtu;
else
{
max_pkt_len = 0;
IP_PANIC();
}
if (pkt->end - pkt->start > max_pkt_len)
{
IPCOM_LOG2(DEBUG2, "RAW: packet to big (%d bytes), allowed size is %d bytes",
(int)(pkt->end - pkt->start), max_pkt_len);
return -IP_ERRNO_ENOBUFS;
}
if (sock->ipcom.type == IP_SOCK_DGRAM)
{
if (netif->link_raw_output == IP_NULL)
{
IPCOM_LOG1(DEBUG2, "RAW: interface %s does not support"
"IP_SOCK_DGRAM type IP_AF_PACKET sockets", netif->ipcom.name);
return -IP_ERRNO_ENOSYS;
}
if (ll_addr->sll_protocol == 0)
{
if (sock->proto == 0)
{
IPCOM_LOG1(DEBUG2, "RAW: protocol was neither specified when the socket %d was created"
" nor in the 'to' address", (int)sock->ipcom.fd);
return -IP_ERRNO_EFAULT;
}
ll_addr->sll_protocol = sock->proto;
}
iplite_if_lock(netif);
ret = netif->link_raw_output(netif, ll_addr, pkt);
goto leave;
}
ip_assert(netif->ipcom.drv_output != IP_NULL);
iplite_if_lock(netif);
ret = iplite_if_output(netif, pkt);
leave:
(void)iplite_if_unlock(netif);
return ret;
}
/*
*===========================================================================
* iplite_packet_input
*===========================================================================
* Context: Any non-interrupt context.
* Description: Inputs a packet to the stack.
* Parameters: netif - The interface the packet was received on.
* pkt - The received packet. pkt->start is the offset to the
* the link layer header.
* Returns:
*
*/
IP_GLOBAL Ip_bool
iplite_packet_input(Iplite_netif *netif, Ipcom_pkt *pkt)
{
int i;
Ip_u16 frame_type;
Ip_bool continue_process = IP_TRUE;
ip_assert(iplite.num_packet_sock > 0);
if (netif->link_get_frame_info == IP_NULL)
{
IPCOM_LOG1(DEBUG2, "RAW: packet sockets is not supported by interface %d",
(int)netif->ipcom.ifindex);
return IP_TRUE;
}
i = netif->link_get_frame_info(netif, pkt, IP_NULL, &frame_type, IP_NULL, IP_NULL);
if (i < 0)
{
IPCOM_LOG1(DEBUG2, "RAW: failed to get information about the frame (%d)", -i);
return IP_TRUE;
}
pkt->ipstart = pkt->start; /* to avoid assert in clone() */
/* Give to all sockets that matches the protocol */
if (iplite_raw_input(pkt, IP_FALSE, frame_type, IP_NULL, 0, IP_NULL, 0,
(Iplite_socklookup)iplite_packet_socklookup) == -IP_ERRNO_ENODATA)
continue_process = IP_FALSE;
/* Give to all sockets that should match any protocol -> all packets */
if (iplite_raw_input(pkt, IP_FALSE, 0, IP_NULL, 0, IP_NULL, 0,
(Iplite_socklookup)iplite_packet_socklookup) == -IP_ERRNO_ENODATA)
continue_process = IP_FALSE;
if (!continue_process)
ipcom_pkt_free(pkt);
return continue_process;
}
#endif /* IPCOM_USE_PACKET */
/*
*===========================================================================
* iplite_raw_input
*===========================================================================
* Description: Generic input handler for packet.
* Parameters: pkt - The received packet.
* take_ownership - Set to IP_TRUE if this function should control
* the lifetime of the packet.
* proto - The protocol number.
* src_addr - The address (Ipv4 or IPv6) of the sender.
* src_port - The source port.
* dst_addr - The address (Ipv4 or IPv6) of the receiver (this system).
* src_port - The destination port.
* 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_raw_input(Ipcom_pkt *pkt, Ip_bool take_ownership, int proto,
IP_CONST void *src_addr, Ip_u16 src_port, IP_CONST void *dst_addr, Ip_u16 dst_port,
Iplite_socklookup socklookup)
{
int next = 0; /* start from 0 because bound sockets start from 0 */
Ip_bool org_pkt_queued = IP_FALSE;
int matching_sock = 0;
Iplite_socket *sock;
Ipcom_pkt *clone;
Ip_u32 checksum;
Ip_bool checksum_ok = IP_FALSE;
#ifdef IP_PORT_OSE5
iplite.raw_input_id++;
#endif
while (IP_NULL != (sock = socklookup(proto, dst_addr, dst_port, src_addr, src_port, &next)))
{
if (checksum_ok == IP_FALSE
&& IP_BIT_ISSET(sock->flags, IPLITE_SOCKET_FLAG_ADDCHECKSUM)
&& sock->proto != IP_IPPROTO_ICMPV6
&& sock->proto != IP_IPPROTO_UDP)
{
/* The checksum must be checked for this packet
UDP and ICMPv6 packets has already been checked */
checksum = ipcom_in_checksum_update(&pkt->data[pkt->start],
(Ip_size_t) (pkt->end - pkt->start));
if (ipcom_in_checksum_finish(checksum + pkt->chk) != 0)
{
/* Wrong checksum */
IPLITE_STATS(raw_input_badchksum++);
matching_sock = -IP_ERRNO_EINVAL;
goto leave;
}
checksum_ok = IP_TRUE;
}
#ifdef IP_PORT_OSE5
if (iplite.raw_input_id == sock->raw_input_id)
continue;
sock->raw_input_id = iplite.raw_input_id;
#endif
if (org_pkt_queued || !take_ownership)
{
clone = iplite_pkt_clone(pkt);
if (clone == IP_NULL)
break;
}
else
clone = pkt;
clone->fd = sock->ipcom.fd;
if (sock->ipcom.event_cb)
sock->ipcom.event_cb((Ipcom_socket *)sock, clone, IP_SOEVENT_CB_INPKT);
if (iplite_queue_received_packet(clone, sock) < 0)
{
if(clone != pkt)
ipcom_pkt_free(clone);
continue;
}
if (sock->ipcom.event_cb)
sock->ipcom.event_cb((Ipcom_socket *)sock, pkt, IP_SOEVENT_CB_SELREAD);
if (pkt == clone)
org_pkt_queued = IP_TRUE;
matching_sock++;
}
leave:
if (take_ownership && !org_pkt_queued)
ipcom_pkt_free(pkt);
return matching_sock;
}
/*
*===========================================================================
* iplite_raw_output
*===========================================================================
* Description: Dispatches the call to the appropriate output handler.
* 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_raw_output(Iplite_socket *sock, IP_CONST struct Ip_sockaddr *to, Ipcom_pkt *pkt)
{
ip_assert(sock->ipcom.type == IP_SOCK_RAW);
switch (sock->ipcom.domain)
{
#ifdef IPCOM_USE_INET
case IP_AF_INET :
return iplite_ip4_sendto(sock, to, pkt);
#endif
#ifdef IPCOM_USE_INET6
case IP_AF_INET6 :
return iplite_ip6_sendto(sock, to, pkt);
#endif
#ifdef IPIPSEC2
case IP_AF_KEY :
return ipipsec_pfkeyv2_input((Ipcom_socket *)sock, IP_NULL, pkt);
#endif
default :
/* Invalid domain */
return -IP_ERRNO_EAFNOSUPPORT;
}
}
#endif /* !defined(IPLITE_ONE_FILE) || defined(IPLITE_C) */
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/