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

398 lines
12 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_netlink_kern.c,v $ $Revision: 1.7.10.1 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_netlink_kern.c,v $
* $Author: jsheng $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "ipnet_config.h"
#if defined(IPNET)
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_clib.h>
#include <ipcom_sysvar.h>
#include <ipcom_inet.h>
#include <ipcom_syslog.h>
#include <ipcom_hash.h>
#include "ipnet_h.h"
#include "ipnet.h"
#ifdef IPTCP
#include "iptcp.h"
#endif
#include <private/ipmip_netlink_kern.h>
#ifdef IPMIP6
#include <private/ipmip6_netlink_kern.h>
#endif
#ifdef IPMIP4
#include <private/ipmip4_netlink_kern.h>
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIP_PKT_HAS_INFO(pkt) (pkt->next_extra_data != 0)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipmip_netlink_kern
{
Ipcom_hash *handles[IPCOM_VR_MAX];
} Ipmip_netlink_kern_t;
/**/
IP_STATIC Ipmip_netlink_kern_t *ipmip_netlink_kern = IP_NULL;
IP_STATIC unsigned
ipmip_netlink_kern_handle_obj_hash(Ipmip_netlink_kern_handle_t *hdr)
{
return ipcom_hash_update(hdr, sizeof(*hdr), 0);
}
IP_STATIC Ip_bool
ipmip_netlink_kern_handle_cmp_hash(Ipmip_netlink_kern_handle_t *obj1,
Ipmip_netlink_kern_handle_t *obj2)
{
/**/
return obj1->mip_facility == obj2->mip_facility && obj1->mip_ident == obj2->mip_ident;
}
IP_STATIC Ip_bool
ipmip_netlink_kern_rt_flow_cmp(struct Ipnet_route_entry_struct *rtentry,
struct Ipnet_dst_cache_struct *dst)
{
struct Ipnet_route_func_info *rtinfo = rtentry->rt_func_info;
Ipmip_netlink_route_flow_info_t *rtflow = (Ipmip_netlink_route_flow_info_t *)(rtinfo + 1);
if (IP_BIT_ISSET(rtflow->type, IPMIP_NETLINK_KERN_INGRESS_IFINDEX))
{
if (dst->flow_spec.ingress_ifindex == 0)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on INGRESS");
return IP_FALSE;
}
else if (rtflow->ifindex != 0 && rtflow->ifindex != dst->flow_spec.ingress_ifindex)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on INGRESS IFINDEX");
return IP_FALSE;
}
}
if (IP_BIT_ISSET(rtflow->type, IPMIP_NETLINK_KERN_EGRESS_IFINDEX))
{
if (dst->flow_spec.ingress_ifindex != 0)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on EGRESS");
return IP_FALSE;
}
else if (rtflow->ifindex != 0 && rtflow->ifindex != dst->flow_spec.egress_ifindex)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on EGRESS IFINDEX");
return IP_FALSE;
}
}
if ((rtflow->flow.key.u64[0] != (dst->flow_spec.mip.key.u64[0] & rtflow->flow.mask.u64[0])) ||
(rtflow->flow.key.u64[1] != (dst->flow_spec.mip.key.u64[1] & rtflow->flow.mask.u64[1])) ||
(rtflow->flow.key.u64[2] != (dst->flow_spec.mip.key.u64[2] & rtflow->flow.mask.u64[2])))
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on FLOW");
return IP_FALSE;
}
/* Clear the flow spec values from this dst cache that arent used, just to speed up the cmps a bit */
dst->flow_spec.mip.key.u64[0] = dst->flow_spec.mip.key.u64[0] & rtflow->flow.mask.u64[0];
dst->flow_spec.mip.key.u64[1] = dst->flow_spec.mip.key.u64[1] & rtflow->flow.mask.u64[1];
dst->flow_spec.mip.key.u64[2] = dst->flow_spec.mip.key.u64[2] & rtflow->flow.mask.u64[2];
/* Store the mask */
ipcom_memcpy(&dst->flow_spec.mip.mask, &rtflow->flow.mask, sizeof(rtflow->flow.mask));
/* Setup the MIP DST cache init routine based on the Route's callbacks */
if (rtflow->flow_handle != IP_NULL)
{
dst->mip.flow_handle = rtflow->flow_handle;
dst->mip.flow_aux = ipcom_malloc(rtinfo->rt_info_size);
if(IP_NULL == dst->mip.flow_aux)
return IP_FALSE;
ipcom_memcpy(dst->mip.flow_aux, rtinfo, rtinfo->rt_info_size);
}
/**/
return IP_TRUE;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_bool
ipmip_netlink_kern_rt_flow_set(struct Ipnet_route_func_info *rtinfo,
Ipmip_netlink_kern_compare_t *srccmp,
Ipnet_dst_cache_mip_handle flow_handle)
{
Ipmip_netlink_route_flow_info_t *rtflow = (Ipmip_netlink_route_flow_info_t *)(rtinfo + 1);
/* Set compare function */
rtinfo->rt_flow_cmp = (Ipnet_route_flow_spec_cmp_t)ipmip_netlink_kern_rt_flow_cmp;
/* Set init function */
rtflow->flow_handle = flow_handle;
if (IP_LIKELY(srccmp != IP_NULL))
{
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_PROTO))
{
rtflow->flow.mask.u8[1] = 0xFF;
rtflow->flow.key.u8[1] = srccmp->srcmac.proto;
}
/* Create the flow MASK */
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_TUNNEL|IPMIP_NETLINK_KERN_SRCMAC))
{
/* First field is ENCAP size */
rtflow->flow.mask.u8[0] = 0xFF;
rtflow->flow.key.u8[0] = srccmp->srcmac.srcmac_len;
ipcom_memcpy(&rtflow->flow.key.u32[1], &srccmp->srcmac.hdr.opaque[0], srccmp->srcmac.srcmac_len);
ipcom_memset(&rtflow->flow.mask.u32[1], 0xFF, srccmp->srcmac.srcmac_len);
}
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_INGRESS_IFINDEX|IPMIP_NETLINK_KERN_EGRESS_IFINDEX))
rtflow->ifindex = srccmp->srcmac.ifindex;
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_GREKEY))
{
rtflow->flow.key.u32[5] = srccmp->srcmac.gre_key;
rtflow->flow.mask.u32[5] = 0xFFFFFFFF;
}
rtflow->type = srccmp->srcmac_type;
}
return IP_TRUE;
}
IP_GLOBAL Ipmip_netlink_kern_handle_t *
ipmip_netlink_kern_handle_get(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
/**/
return (Ipmip_netlink_kern_handle_t *)ipcom_hash_get(ipmip_netlink_kern->handles[vr], handle);
}
IP_GLOBAL void
ipmip_netlink_kern_handle_add(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
ipcom_hash_add(ipmip_netlink_kern->handles[vr], handle);
}
IP_GLOBAL Ipmip_netlink_kern_handle_t *
ipmip_netlink_kern_handle_del(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
Ipmip_netlink_kern_handle_t *rhandle = ipmip_netlink_kern_handle_get(vr, handle);
if (rhandle)
ipcom_hash_remove(ipmip_netlink_kern->handles[vr], rhandle);
/**/
return rhandle;
}
IP_GLOBAL void
ipmip_netlink_kern_handle_free(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
handle = ipmip_netlink_kern_handle_del(vr, handle);
if (handle)
ipcom_free(handle);
}
IP_GLOBAL void
ipmip_netlink_kern_if_include(Ipnet_netif *netif)
{
IP_BIT_CLR(netif->flags2, IPNET_IFF2_NO_GLOBAL_SRC);
}
IP_GLOBAL void
ipmip_netlink_kern_if_exclude(Ipnet_netif *netif)
{
IP_BIT_SET(netif->flags2, IPNET_IFF2_NO_GLOBAL_SRC);
}
IP_GLOBAL void
ipmip_netlink_kern_hoa_activate(Ipnet_netif *netif,
struct Ip_rtattr *rta)
{
Ipnet_socket *sock = IP_NULL;
Ipnet_socket *next_sock;
#ifdef IPCOM_USE_INET6
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in6_addr))
{
Ipnet_ip6_addr_entry *entry = ipnet_ip6_get_addr_entry(IP_RTA_DATA(rta), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP6_ADDR_FLAG_HOMEADDRESS))
{
/* Kickstart list */
#ifdef IPTCP
sock = entry->socket_list;
#endif
}
}
#endif
#ifdef IPCOM_USE_INET
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in_addr))
{
Ipnet_ip4_addr_entry *entry = ipnet_ip4_get_addr_entry(IP_GET_32ON8(IP_RTA_DATA(rta)), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP4_ADDR_FLAG_HOMEADDRESS))
{
#ifdef IPTCP
sock = entry->socket_list;
#endif
IP_BIT_SET(entry->flags, IPNET_IP4_ADDR_FLAG_PREFERRED);
}
}
#endif
#ifdef IPTCP
while (sock != IP_NULL)
{
/* Locate next socket with the same address */
next_sock = sock->addr_next;
/* Do we have a notify CB */
if (sock->notify_cb != IP_NULL)
{
/* Kickstart it */
(*sock->notify_cb) (sock, IPTCP_SOCKET_EVENT_KICKSTART);
}
/* Do next socket */
sock = next_sock;
}
#endif
}
IP_GLOBAL void
ipmip_netlink_kern_hoa_deactivate(Ipnet_netif *netif,
struct Ip_rtattr *rta)
{
#ifdef IPCOM_USE_INET6
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in6_addr))
{
Ipnet_ip6_addr_entry *entry = ipnet_ip6_get_addr_entry(IP_RTA_DATA(rta), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP6_ADDR_FLAG_HOMEADDRESS))
{
/* Kickstart list */
}
}
#endif
#ifdef IPCOM_USE_INET
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in_addr))
{
Ipnet_ip4_addr_entry *entry = ipnet_ip4_get_addr_entry(IP_GET_32ON8(IP_RTA_DATA(rta)), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP4_ADDR_FLAG_HOMEADDRESS))
{
IP_BIT_CLR(entry->flags, IPNET_IP4_ADDR_FLAG_PREFERRED);
}
}
#endif
}
IP_GLOBAL void
ipmip_rtnetlink_init(void)
{
int i;
/* Create the handles */
ipmip_netlink_kern = ipcom_calloc(1, sizeof(*ipmip_netlink_kern));
for (i = 0; i < IPCOM_VR_MAX; i++)
{
ipmip_netlink_kern->handles[i] = ipcom_hash_new((Ipcom_hash_obj_func) ipmip_netlink_kern_handle_obj_hash,
(Ipcom_hash_key_func) ipmip_netlink_kern_handle_obj_hash,
(Ipcom_hash_cmp_func) ipmip_netlink_kern_handle_cmp_hash);
}
#ifdef IPMIP6
ipmip6_rtnetlink_init();
#endif
#ifdef IPMIP4
ipmip4_rtnetlink_init();
#endif
}
#else
int ipmip_netlink_kern_empty_file = 0;
#endif
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/