862 lines
27 KiB
C
862 lines
27 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_rtnetlink_nae.c,v $ $Revision: 1.2.16.2 $
|
|
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_rtnetlink_nae.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation Jonas Rendel <Jonas.Rendel@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
* Contains netlink handlers for managing Ipv4 and Ipv6 routes as well as
|
|
* MPLS shortcut routes.
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifndef IPCOM_KERNEL
|
|
#define IPCOM_KERNEL
|
|
#endif
|
|
#include "ipnet_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom.h>
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock6.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_route.h>
|
|
#include <ipcom_errno.h>
|
|
|
|
#include "ipnet_h.h"
|
|
#include "ipnet_ctrl.h"
|
|
#include "ipnet_route.h"
|
|
#include "ipnet_netlink_h.h"
|
|
#include "ipnet_rtnetlink_h.h"
|
|
#include "ipcom_sock.h"
|
|
#include "ipcom_forwarder.h"
|
|
#include "ipnet_loopback.h"
|
|
|
|
#ifdef IP_PORT_LKM
|
|
#include "ipcom_lkm.h" /* Needed for Linux PPP interface config */
|
|
#endif /* IP_PORT_LKM */
|
|
|
|
#include "ipnet_eth.h"
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_IPSEC
|
|
#include <ipipsec_h.h>
|
|
#endif
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
#define IP_IN4_IS_ADDR_MULTICAST(x) (((x) & ip_htonl(0xf0000000)) == ip_ntohl (0xe0000000))
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
typedef struct Ipnet_rtnetlink_fwc_family
|
|
{
|
|
struct
|
|
{
|
|
Ip_ptrdiff_t *hash;
|
|
Ip_ptrdiff_t *done;
|
|
int aborted;
|
|
int cont;
|
|
} state;
|
|
|
|
/* Requested */
|
|
struct Ip_nlmsghdr *nlmsg;
|
|
Ip_u8 family;
|
|
|
|
/* Buffering */
|
|
Ipnet_netlink_mem_t *mem;
|
|
}
|
|
Ipnet_rtnetlink_fwc_family_t;
|
|
|
|
|
|
typedef struct Ipnet_rtnetlink_sac_family
|
|
{
|
|
struct
|
|
{
|
|
Ip_ptrdiff_t *hash;
|
|
Ip_ptrdiff_t *done;
|
|
int aborted;
|
|
int cont;
|
|
} state;
|
|
|
|
/* Requested */
|
|
struct Ip_nlmsghdr *nlmsg;
|
|
Ip_u8 family;
|
|
|
|
/* Buffering */
|
|
Ipnet_netlink_mem_t *mem;
|
|
}
|
|
Ipnet_rtnetlink_sac_family_t;
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_fwcache_entry(Ipnet_rtnetlink_fwc_family_t *param,
|
|
Ip_u32 hash_entry,
|
|
int domain,
|
|
Ip_u32 vlan,
|
|
void *dst,
|
|
Ip_size_t dst_size,
|
|
Ip_u8 *mac,
|
|
Ip_u32 unused)
|
|
{
|
|
struct Ip_nlmsghdr *nlh;
|
|
struct Ip_fwcmsg *fwc;
|
|
|
|
|
|
nlh = ipnet_netlink_nlmsg_sz_begin(param->mem, param->nlmsg->nlmsg_seq, IP_RTM_NEWFWCACHE, IP_NLM_F_MULTI);
|
|
if (!nlh)
|
|
return -1;
|
|
|
|
fwc = ipnet_netlink_sz_put(param->mem, IP_NULL, sizeof (*fwc));
|
|
if (!fwc)
|
|
return -1;
|
|
|
|
/*
|
|
* Add route message header
|
|
*/
|
|
fwc->fwc_family = domain;
|
|
fwc->fwc_entry = hash_entry;
|
|
fwc->fwc_core = ipcom_nae_current_core();
|
|
fwc->fwc_nae = ipcom_nae_id();
|
|
fwc->fwc_port = mac[0];
|
|
fwc->fwc_index = ipcom_nae.nae_port[fwc->fwc_port].netif->ifindex;
|
|
|
|
/*
|
|
* Add IPSec info
|
|
*/
|
|
if ((mac[1] & 0x0f) == IPCOM_FWD_IPSEC_ENCRYPT)
|
|
fwc->sac_encrypt = 1;
|
|
else
|
|
fwc->sac_encrypt = 0;
|
|
|
|
if ((mac[1] & 0x0f) == IPCOM_FWD_IPSEC_DECRYPT)
|
|
fwc->sac_decrypt = 1;
|
|
else
|
|
fwc->sac_decrypt = 0;
|
|
|
|
/*
|
|
* Put destination address
|
|
*/
|
|
if (!ipnet_rtnetlink_rta_sz_put(param->mem, IP_FWC_DST, dst_size, dst))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(param->mem, IP_FWC_LLADDR, 6, &mac[2]))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(param->mem, IP_FWC_UNUSED, sizeof(Ip_u32), &unused))
|
|
return -1;
|
|
|
|
if (0 != vlan && !ipnet_rtnetlink_rta_sz_put(param->mem, IP_FWC_VLAN, sizeof(vlan), &vlan))
|
|
return -1;
|
|
|
|
/*
|
|
* Done
|
|
*/
|
|
return ipnet_netlink_nlmsg_sz_end(param->mem, nlh);
|
|
}
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_fwcache_foreach_inet(Ipnet_rtnetlink_fwc_family_t *param)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int f4_limit = ipcom_nae_shm->fw_v4_entries * IPCOM_FORWARDER_TRUE_CACHE_WAYS;
|
|
#ifdef IPCOM_USE_FORWARDER_VLAN
|
|
unsigned int f6_limit = ipcom_nae_shm->fw_v6_entries * IPCOM_FORWARDER_TRUE_CACHE_WAYS + f4_limit;
|
|
#endif
|
|
|
|
if (*param->state.hash < f4_limit)
|
|
{
|
|
/* Going through the 'ordinary' v4 */
|
|
for (i = *param->state.hash; i < f4_limit; i++)
|
|
{
|
|
fw_cache_entry_v4_t *e4 = &ipcom_nae.fw_cache_tbl_v4[i];
|
|
if (e4->ip4.rci == ipnet->route_cache_id)
|
|
{
|
|
/* Got a player */
|
|
if (0 > ipnet_rtnetlink_fwcache_entry(param, i, IP_AF_INET, 0, &e4->ip4.addr, sizeof(e4->ip4.addr), (Ip_u8 *)e4->mac_if.dst_mac, IPCOM_FW_NBR_UNUSED_GET(e4) != 0))
|
|
goto aborted;
|
|
}
|
|
}
|
|
|
|
*param->state.hash = f4_limit;
|
|
}
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_VLAN
|
|
if (*param->state.hash < f6_limit)
|
|
{
|
|
/* We're going through the VLAN v4 */
|
|
for (i = *param->state.hash; i < f6_limit; i++)
|
|
{
|
|
fw_cache_entry_vlan_t *ev = (fw_cache_entry_vlan_t *)&ipcom_nae.fw_cache_tbl_v6[i - f4_limit];
|
|
if (ev->ipvlan.rci == ipnet->route_cache_id && ev->ipvlan.type == IPCOM_FORWARDER_PACKET_TYPE_IPV4_VLAN)
|
|
{
|
|
/* Got a player */
|
|
if (0 > ipnet_rtnetlink_fwcache_entry(param, i - f4_limit, IP_AF_INET, ev->ipvlan.vlan_id, &ev->ipvlan.a.addr_v4, sizeof(ev->ipvlan.a.addr_v4), (Ip_u8 *)ev->mac_if.dst_mac, IPCOM_FW_NBR_UNUSED_GET(ev) != 0))
|
|
goto aborted;
|
|
}
|
|
}
|
|
*param->state.hash = f6_limit;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
aborted:
|
|
param->state.aborted = 1;
|
|
*param->state.hash = (Ip_ptrdiff_t)i;
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_fwcache_foreach_inet6(Ipnet_rtnetlink_fwc_family_t *param)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int f6_limit = ipcom_nae_shm->fw_v6_entries * IPCOM_FORWARDER_TRUE_CACHE_WAYS;
|
|
|
|
if (*param->state.hash < f6_limit)
|
|
{
|
|
/* We're going through the VLAN v4 */
|
|
for (i = *param->state.hash; i < f6_limit; i++)
|
|
{
|
|
fw_cache_entry_v6_t *e6 = &ipcom_nae.fw_cache_tbl_v6[i];
|
|
|
|
if (e6->ip6.rci != ipnet->route_cache_id)
|
|
continue;
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_VLAN
|
|
if (e6->ip6.type == IPCOM_FORWARDER_PACKET_TYPE_IPV6_VLAN)
|
|
{
|
|
fw_cache_entry_vlan_t *ev = (fw_cache_entry_vlan_t *)e6;
|
|
|
|
/* Got a player */
|
|
if (0 > ipnet_rtnetlink_fwcache_entry(param, i, IP_AF_INET6, ev->ipvlan.vlan_id, &ev->ipvlan.a.addr_v6, sizeof(ev->ipvlan.a.addr_v6), (Ip_u8 *)ev->mac_if.dst_mac, IPCOM_FW_NBR_UNUSED_GET(ev) != 0))
|
|
goto aborted;
|
|
}
|
|
else if (e6->ip6.type == IPCOM_FORWARDER_PACKET_TYPE_IPV6)
|
|
#endif
|
|
{
|
|
/* Got a player */
|
|
if (0 > ipnet_rtnetlink_fwcache_entry(param, i, IP_AF_INET6, 0, &e6->ip6.addr, sizeof(e6->ip6.addr), (Ip_u8 *)e6->mac_if.dst_mac, IPCOM_FW_NBR_UNUSED_GET(e6) != 0))
|
|
goto aborted;
|
|
|
|
}
|
|
}
|
|
*param->state.hash = f6_limit;
|
|
}
|
|
|
|
return 0;
|
|
|
|
aborted:
|
|
param->state.aborted = 1;
|
|
*param->state.hash = (Ip_ptrdiff_t)i;
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_IPSEC
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_sacache_entry(Ipnet_rtnetlink_sac_family_t *param,
|
|
Ip_u32 hash_entry,
|
|
int domain,
|
|
Ip_u32 algid,
|
|
Ip_u32 spi,
|
|
void *src,
|
|
void *dst)
|
|
{
|
|
struct Ip_nlmsghdr *nlh;
|
|
struct Ip_sacmsg *sac;
|
|
Ip_size_t size;
|
|
|
|
nlh = ipnet_netlink_nlmsg_sz_begin(param->mem, param->nlmsg->nlmsg_seq, IP_RTM_NEWSACACHE, IP_NLM_F_MULTI);
|
|
if (!nlh)
|
|
return -1;
|
|
|
|
sac = ipnet_netlink_sz_put(param->mem, IP_NULL, sizeof (*sac));
|
|
if (!sac)
|
|
return -1;
|
|
|
|
/*
|
|
* Add SA message header
|
|
*/
|
|
sac->sac_family = (Ip_u8)domain;
|
|
sac->sac_algid = (Ip_u8)algid;
|
|
sac->sac_core = ipcom_nae_current_core();
|
|
sac->sac_nae = ipcom_nae_id();
|
|
sac->sac_entry = hash_entry;
|
|
sac->sac_spi = spi;
|
|
|
|
size = domain == IP_AF_INET ? sizeof(struct Ip_in_addr) : sizeof(struct Ip_in6_addr);
|
|
|
|
/*
|
|
* Put source address
|
|
*/
|
|
if (!ipnet_rtnetlink_rta_sz_put(param->mem, IP_SAC_SRC, size, src))
|
|
return -1;
|
|
|
|
/*
|
|
* Put destination address
|
|
*/
|
|
if (!ipnet_rtnetlink_rta_sz_put(param->mem, IP_SAC_DST, size, dst))
|
|
return -1;
|
|
|
|
/*
|
|
* Done
|
|
*/
|
|
return ipnet_netlink_nlmsg_sz_end(param->mem, nlh);
|
|
}
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_sacache_foreach_inet(Ipnet_rtnetlink_sac_family_t *param)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int sa_limit = ipcom_nae.fw_ipsec_entries * 2;
|
|
|
|
if (*param->state.hash < sa_limit)
|
|
{
|
|
for (i = *param->state.hash; i < sa_limit; i++)
|
|
{
|
|
Ipcom_fw_ipsec_sa_t *fw_ipsec_sa;
|
|
|
|
if (i >= ipcom_nae.fw_ipsec_entries)
|
|
fw_ipsec_sa = &ipcom_nae.fw_cache_tbl_dec[i - ipcom_nae.fw_ipsec_entries]; /* Input SA */
|
|
else
|
|
fw_ipsec_sa = &ipcom_nae.fw_cache_tbl_enc[i]; /* Output SA */
|
|
|
|
if (fw_ipsec_sa->cache_id != 0
|
|
&& fw_ipsec_sa->domain == IP_AF_INET
|
|
&& !IPIPSEC_SA_MARKED_FOR_DELETION(fw_ipsec_sa))
|
|
{
|
|
/* Got a player */
|
|
if (0 > ipnet_rtnetlink_sacache_entry(param, i, fw_ipsec_sa->domain, fw_ipsec_sa->algid,
|
|
fw_ipsec_sa->spi, fw_ipsec_sa->src, fw_ipsec_sa->dst))
|
|
goto aborted;
|
|
}
|
|
}
|
|
|
|
*param->state.hash = sa_limit;
|
|
}
|
|
|
|
return 0;
|
|
|
|
aborted:
|
|
param->state.aborted = 1;
|
|
*param->state.hash = (Ip_ptrdiff_t)i;
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_sacache_foreach_inet6(Ipnet_rtnetlink_sac_family_t *param)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int sa_limit = ipcom_nae.fw_ipsec_entries * 2;
|
|
|
|
if (*param->state.hash < sa_limit)
|
|
{
|
|
for (i = *param->state.hash; i < sa_limit; i++)
|
|
{
|
|
Ipcom_fw_ipsec_sa_t *fw_ipsec_sa;
|
|
|
|
if (i >= ipcom_nae.fw_ipsec_entries)
|
|
fw_ipsec_sa = &ipcom_nae.fw_cache_tbl_dec[i - ipcom_nae.fw_ipsec_entries]; /* Input SA */
|
|
else
|
|
fw_ipsec_sa = &ipcom_nae.fw_cache_tbl_enc[i]; /* Output SA */
|
|
|
|
if (fw_ipsec_sa->cache_id != 0
|
|
&& fw_ipsec_sa->domain == IP_AF_INET6
|
|
&& !IPIPSEC_SA_MARKED_FOR_DELETION(fw_ipsec_sa))
|
|
{
|
|
/* Got a player */
|
|
if (0 > ipnet_rtnetlink_sacache_entry(param, i, fw_ipsec_sa->domain, fw_ipsec_sa->algid,
|
|
fw_ipsec_sa->spi, fw_ipsec_sa->src, fw_ipsec_sa->dst))
|
|
goto aborted;
|
|
}
|
|
}
|
|
*param->state.hash = sa_limit;
|
|
}
|
|
|
|
return 0;
|
|
|
|
aborted:
|
|
param->state.aborted = 1;
|
|
*param->state.hash = (Ip_ptrdiff_t)i;
|
|
return -1;
|
|
}
|
|
#endif
|
|
#endif /* IPCOM_USE_FORWARDER_IPSEC */
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*==========================================================================
|
|
* ipnet_rtnetlink_fwcache_dump_family
|
|
*===========================================================================
|
|
* Description: Get interface info via NETLINK
|
|
* Parameters: data - Message payload.
|
|
* len - Length of message.
|
|
* cb - NETLINK callback entry
|
|
*
|
|
* Returns: 0 - Success
|
|
* <0 - Failure
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_fwcache_dump_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlmsg,
|
|
int family,
|
|
Ip_ptrdiff_t *args)
|
|
|
|
{
|
|
Ipnet_rtnetlink_fwc_family_t param;
|
|
Ip_ptrdiff_t *done = &args[0];
|
|
Ip_ptrdiff_t *s_hash = &args[1];
|
|
Ip_ptrdiff_t *s_continue = &args[2];
|
|
|
|
param.nlmsg = nlmsg;
|
|
param.family = family;
|
|
param.mem = mem;
|
|
|
|
if (*done)
|
|
goto exit_out;
|
|
|
|
param.state.aborted = 0;
|
|
param.state.done = done;
|
|
param.state.hash = s_hash;
|
|
param.state.cont = *s_continue;
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (family == IP_AF_INET)
|
|
ipnet_rtnetlink_fwcache_foreach_inet(¶m);
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (family == IP_AF_INET6)
|
|
ipnet_rtnetlink_fwcache_foreach_inet6(¶m);
|
|
#endif
|
|
|
|
/* Are we aborted? */
|
|
*s_continue = param.state.aborted;
|
|
|
|
/* If not aborted; we're done */
|
|
if (!param.state.aborted)
|
|
*done = 1;
|
|
|
|
exit_out:
|
|
return param.mem->used;
|
|
}
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_fwcache_delfwcache_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlh,
|
|
struct Ip_rtattr **rta,
|
|
int family)
|
|
{
|
|
struct Ip_fwcmsg *fwc = IP_NLMSG_DATA(nlh);
|
|
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_VLAN
|
|
if (IP_NULL != rta[IP_FWC_VLAN - 1])
|
|
{
|
|
fw_cache_entry_vlan_t *ev = (fw_cache_entry_vlan_t *)&ipcom_nae.fw_cache_tbl_v6[fwc->fwc_entry];
|
|
|
|
if (fwc->fwc_entry >= (ipcom_nae_shm->fw_v6_entries * IPCOM_FORWARDER_TRUE_CACHE_WAYS))
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
ev->ipvlan.rci = 0;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (fwc->fwc_family == IP_AF_INET)
|
|
{
|
|
fw_cache_entry_v4_t *e4 = &ipcom_nae.fw_cache_tbl_v4[fwc->fwc_entry];
|
|
|
|
if (fwc->fwc_entry >= (ipcom_nae_shm->fw_v4_entries * IPCOM_FORWARDER_TRUE_CACHE_WAYS))
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
e4->ip4.rci = 0;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (fwc->fwc_family == IP_AF_INET6)
|
|
{
|
|
fw_cache_entry_v6_t *e6 = &ipcom_nae.fw_cache_tbl_v6[fwc->fwc_entry];
|
|
|
|
if (fwc->fwc_entry >= (ipcom_nae_shm->fw_v6_entries * IPCOM_FORWARDER_TRUE_CACHE_WAYS))
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
e6->ip6.rci = 0;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
return -IP_ERRNO_ENOENT;
|
|
}
|
|
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_IPSEC
|
|
/*
|
|
*==========================================================================
|
|
* ipnet_rtnetlink_sacache_dump_family
|
|
*===========================================================================
|
|
* Description: Get SA cache via NETLINK
|
|
* Parameters: data - Message payload.
|
|
* len - Length of message.
|
|
* cb - NETLINK callback entry
|
|
*
|
|
* Returns: 0 - Success
|
|
* <0 - Failure
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_sacache_dump_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlmsg,
|
|
int family,
|
|
Ip_ptrdiff_t *args)
|
|
|
|
{
|
|
Ipnet_rtnetlink_sac_family_t param;
|
|
Ip_ptrdiff_t *done = &args[0];
|
|
Ip_ptrdiff_t *s_hash = &args[1];
|
|
Ip_ptrdiff_t *s_continue = &args[2];
|
|
|
|
param.nlmsg = nlmsg;
|
|
param.family = family;
|
|
param.mem = mem;
|
|
|
|
if (*done)
|
|
goto exit_out;
|
|
|
|
param.state.aborted = 0;
|
|
param.state.done = done;
|
|
param.state.hash = s_hash;
|
|
param.state.cont = *s_continue;
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (family == IP_AF_INET)
|
|
ipnet_rtnetlink_sacache_foreach_inet(¶m);
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (family == IP_AF_INET6)
|
|
ipnet_rtnetlink_sacache_foreach_inet6(¶m);
|
|
#endif
|
|
|
|
/* Are we aborted? */
|
|
*s_continue = param.state.aborted;
|
|
|
|
/* If not aborted; we're done */
|
|
if (!param.state.aborted)
|
|
*done = 1;
|
|
|
|
exit_out:
|
|
return param.mem->used;
|
|
}
|
|
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_sacache_delsacache_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlh,
|
|
struct Ip_rtattr **rta,
|
|
int family)
|
|
{
|
|
struct Ip_sacmsg *sac = IP_NLMSG_DATA(nlh);
|
|
|
|
#if defined(IPCOM_USE_INET) && defined(IPCOM_USE_INET6)
|
|
if (sac->sac_family == IP_AF_INET || sac->sac_family == IP_AF_INET6)
|
|
#elif defined(IPCOM_USE_INET)
|
|
if (sac->sac_family == IP_AF_INET)
|
|
#elif defined(IPCOM_USE_INET6)
|
|
if (sac->sac_family == IP_AF_INET6)
|
|
#endif
|
|
{
|
|
Ipcom_fw_ipsec_sa_t *fw_ipsec_sa;
|
|
|
|
if (sac->sac_entry >= (ipcom_nae.fw_ipsec_entries * 2))
|
|
return -IP_ERRNO_EINVAL;
|
|
else if (sac->sac_entry >= ipcom_nae.fw_ipsec_entries)
|
|
fw_ipsec_sa = &ipcom_nae.fw_cache_tbl_dec[sac->sac_entry - ipcom_nae.fw_ipsec_entries]; /* Input SA */
|
|
else
|
|
fw_ipsec_sa = &ipcom_nae.fw_cache_tbl_enc[sac->sac_entry]; /* Output SA */
|
|
ipcom_memset(fw_ipsec_sa, 0, sizeof(*fw_ipsec_sa));
|
|
return 0;
|
|
}
|
|
|
|
return -IP_ERRNO_ENOENT;
|
|
}
|
|
#endif /* IPCOM_USE_FORWARDER_IPSEC */
|
|
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_nae_setnae_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlh,
|
|
struct Ip_rtattr **rta,
|
|
int family)
|
|
{
|
|
(void) mem;
|
|
(void) nlh;
|
|
(void) rta;
|
|
(void) family;
|
|
return -IP_ERRNO_ENOSYS;
|
|
}
|
|
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_nae_getnae_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlhreq,
|
|
struct Ip_rtattr **rta,
|
|
int family)
|
|
{
|
|
struct Ip_nlmsghdr *nlh;
|
|
struct Ip_naemsg *nae;
|
|
Ip_u32 tmp32;
|
|
Ip_u64 tmp64;
|
|
unsigned long ticks;
|
|
unsigned hz;
|
|
int i;
|
|
|
|
nlh = ipnet_netlink_nlmsg_sz_begin(mem, nlhreq->nlmsg_seq, IP_RTM_NEWNAE, 0);
|
|
if (!nlh)
|
|
return -1;
|
|
|
|
nae = ipnet_netlink_sz_put(mem, IP_NULL, sizeof (*nae));
|
|
if (!nae)
|
|
return -1;
|
|
|
|
nae->nae_family = IP_AF_UNSPEC;
|
|
nae->nae_id = ipcom_nae_id();
|
|
nae->nae_core = ipcom_nae_current_core();
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_enable;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_ENABLE, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_started;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_STARTED, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
ipcom_nae_tick_get(&ticks, &hz);
|
|
tmp64 = (Ip_u64)ticks;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_TICK_COUNT, sizeof(Ip_u64), &tmp64))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)hz;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_TICK_HZ, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_selective_invalid;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_SELECTIVE_INVALID, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_total_invalid;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_TOTAL_INVALID, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_invalid_delete;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_INVALID_DELETE, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_invalid_incomplete;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_INVALID_INCOMPLETE, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_invalid_lladdr;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_INVALID_LLADDR, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_neigh_timeout;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_NEIGH_DELETE_TIMEOUT, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_neigh_external_delete;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_NEIGH_DELETE_EXTERNAL, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_neigh_garbage_collect;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_NEIGH_DELETE_GARBAGE_COLLECT, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_neigh_flushed;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_NEIGH_DELETE_FLUSHED, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_neigh_failed;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_NEIGH_DELETE_FAILED, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_neigh_resource;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_NEIGH_DELETE_RESOURCE, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_entries_inet;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_CURRENT_INET, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_nae_shm->fw_v4_entries;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_TOTAL_INET, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_entries_inet6;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_CURRENT_INET6, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_nae_shm->fw_v6_entries;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_TOTAL_INET6, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_collissions;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_COLLISSIONS, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipcom_forwarder_fw_collissions_invalidate;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_COLLISSIONS_INVALIDATE, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
tmp32 = (Ip_u32)ipnet->route_cache_id;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_FWCACHE_ROUTE_CACHE_ID, sizeof(Ip_u32), &tmp32))
|
|
return -1;
|
|
|
|
if (IP_NULL != ipcom_nae_shm_table.nae_shm_get_pkt_pool)
|
|
{
|
|
int pool_mtu, pool_max, pool_avail, pool_numa;
|
|
char *pool_name;
|
|
|
|
for (i = 0;;i++)
|
|
{
|
|
struct Ip_rtattr *rta_nest;
|
|
if (0 > (*ipcom_nae_shm_table.nae_shm_get_pkt_pool) (i, &pool_max, &pool_avail, &pool_mtu, &pool_numa, &pool_name))
|
|
break;
|
|
|
|
rta_nest = ipnet_rtnetlink_rta_sz_nested_begin(mem, IP_NAE_PKT_POOL);
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_PKTPOOL_NAME, ipcom_strlen(pool_name) + 1, pool_name))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_PKTPOOL_MTU, sizeof(Ip_u32), &pool_mtu))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_PKTPOOL_SIZE, sizeof(Ip_u32), &pool_max))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_PKTPOOL_AVAIL, sizeof(Ip_u32), &pool_avail))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_PKTPOOL_NUMA, sizeof(Ip_u32), &pool_numa))
|
|
return -1;
|
|
|
|
ipnet_rtnetlink_rta_sz_nested_end(mem, rta_nest);
|
|
}
|
|
}
|
|
|
|
/* */
|
|
{
|
|
Ipcom_forwarder_capability_t *cap_e, *cap_v;
|
|
|
|
for (cap_e = IPCOM_LIST_FIRST(&ipcom_nae.capability); cap_e != IP_NULL; cap_e = IPCOM_LIST_NEXT(&cap_e->next))
|
|
{
|
|
struct Ip_rtattr *rta_nest;
|
|
|
|
rta_nest = ipnet_rtnetlink_rta_sz_nested_begin(mem, IP_NAE_CAPABILITY);
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_PKTPOOL_NAME, ipcom_strlen(cap_e->cap) + 1, cap_e->cap))
|
|
return -1;
|
|
|
|
for (cap_v = IPCOM_LIST_FIRST(&cap_e->values); cap_v != IP_NULL; cap_v = IPCOM_LIST_NEXT(&cap_v->next))
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_NAE_CAPABILITY_VALUE, ipcom_strlen(cap_v->cap) + 1, cap_v->cap))
|
|
return -1;
|
|
|
|
ipnet_rtnetlink_rta_sz_nested_end(mem, rta_nest);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Done
|
|
*/
|
|
return ipnet_netlink_nlmsg_sz_end(mem, nlh);
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
#endif /* IPNET_USE_NETLINK */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|