963 lines
32 KiB
C
963 lines
32 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ip_nae.c,v $ $Revision: 1.2.40.2 $
|
|
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ip_nae.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPCOM_KERNEL
|
|
#undef IPCOM_KERNEL
|
|
#endif
|
|
#include "ipnet_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_cmd.h>
|
|
#include <ipcom_getopt.h>
|
|
#include <ipcom_shell.h>
|
|
#include <ipcom_sysctl.h>
|
|
|
|
#include "ipnet.h"
|
|
#include "ipnet_cmd.h"
|
|
#include "ipnet_ctrl.h"
|
|
#include "ipnet_h.h"
|
|
#include "ipnet_sysctl.h"
|
|
|
|
#include "ipnet_cmd_ip.h"
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
|
|
#include <ipcom_forwarder.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_FWC_MAIN_HELP,
|
|
IPNET_IP_FWC_MAIN_LIST,
|
|
IPNET_IP_FWC_MAIN_FLUSH
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_FWC_MODIFY_DEVNAME,
|
|
IPNET_IP_FWC_MODIFY_HASH,
|
|
IPNET_IP_FWC_MODIFY_DST
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_SAC_MAIN_HELP,
|
|
IPNET_IP_SAC_MAIN_LIST,
|
|
IPNET_IP_SAC_MAIN_FLUSH
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_SAC_MODIFY_HASH
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_NAE_MAIN_HELP,
|
|
IPNET_IP_NAE_MAIN_LIST
|
|
};
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
typedef struct Ipnet_cmd_ip_module_fwc_filter_struct
|
|
{
|
|
Ip_u64 mask;
|
|
|
|
int ifindex;
|
|
Ip_u32 hash;
|
|
Ipnet_ip_prefix_t dst;
|
|
|
|
} Ipnet_cmd_ip_module_fwc_filter_t;
|
|
|
|
|
|
typedef struct Ipnet_cmd_ip_module_sac_filter_struct
|
|
{
|
|
Ip_u64 mask;
|
|
|
|
Ip_u32 hash;
|
|
|
|
} Ipnet_cmd_ip_module_sac_filter_t;
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_fwc_main[] =
|
|
{
|
|
{ IPNET_IP_FWC_MAIN_HELP, "help" },
|
|
|
|
{ IPNET_IP_FWC_MAIN_LIST, "show" },
|
|
{ IPNET_IP_FWC_MAIN_LIST, "list" },
|
|
{ IPNET_IP_FWC_MAIN_LIST, "lst" },
|
|
|
|
{ IPNET_IP_FWC_MAIN_FLUSH, "flush" },
|
|
|
|
{ IPNET_IP_SAC_MAIN_LIST, "show" },
|
|
{ IPNET_IP_SAC_MAIN_LIST, "list" },
|
|
{ IPNET_IP_SAC_MAIN_LIST, "lst" },
|
|
|
|
{ IPNET_IP_SAC_MAIN_FLUSH, "flush" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_fwc_modify[] =
|
|
{
|
|
{ IPNET_IP_FWC_MODIFY_HASH, "hash" },
|
|
{ IPNET_IP_FWC_MODIFY_DEVNAME, "dev" },
|
|
{ IPNET_IP_FWC_MODIFY_DST, "dst" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_IPSEC
|
|
static Ipcom_cmd_int_str_map ipnet_ip_sac_modify[] =
|
|
{
|
|
{ IPNET_IP_SAC_MODIFY_HASH, "hash" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
#endif
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_nae_main[] =
|
|
{
|
|
{ IPNET_IP_NAE_MAIN_HELP, "help" },
|
|
|
|
{ IPNET_IP_NAE_MAIN_LIST, "show" },
|
|
{ IPNET_IP_NAE_MAIN_LIST, "list" },
|
|
{ IPNET_IP_NAE_MAIN_LIST, "lst" },
|
|
{ IPNET_IP_NAE_MAIN_LIST, "get" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_nae_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip nae - Display and modify the IPNET NAE information"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip nae show"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip fwc help"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "DESCRIPTION"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " help Display usage information"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " show Show NAE information"IP_LF);
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_nae_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
struct Ip_naemsg *nae = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
if (cfg->is_silent)
|
|
return 0;
|
|
|
|
ipnet_ip_parse_reply(nlmsg, IP_NAE_MAX, sizeof(struct Ip_naemsg));
|
|
|
|
ipnet_ip_stdio_printf(cfg, "nae %s %d", ipcom_nae_control_core() == nae->nae_core? "ctrl" : "dataplane", nae->nae_id);
|
|
ipnet_ip_stdio_printf(cfg, " core %d", nae->nae_core);
|
|
ipnet_ip_stdio_printf(cfg, " enabled %s", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_ENABLE])? "yes" : "no");
|
|
ipnet_ip_stdio_printf(cfg, " started %s", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_STARTED])? "yes" : "no");
|
|
ipnet_ip_stdio_printf(cfg, " ticks %llu", ipnet_ip_rta_u64(nlmsg->rta[IP_NAE_TICK_COUNT]));
|
|
ipnet_ip_stdio_printf(cfg, " hz %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_TICK_HZ]));
|
|
ipnet_ip_stdio_printf(cfg, " rtcache %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_ROUTE_CACHE_ID]));
|
|
ipnet_ip_stdio_printf(cfg, " colls %d/%d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_COLLISSIONS]), ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_COLLISSIONS_INVALIDATE]));
|
|
ipnet_ip_stdio_printf(cfg, " invalid %d/%d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_SELECTIVE_INVALID]), ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_TOTAL_INVALID]));
|
|
ipnet_ip_stdio_printf(cfg, " inet %d/%d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_CURRENT_INET]), ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_TOTAL_INET]));
|
|
ipnet_ip_stdio_printf(cfg, " inet6 %d/%d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_CURRENT_INET6]), ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_TOTAL_INET6]));
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_NAE_CAPABILITY])
|
|
{
|
|
struct Ip_rtattr **caps = ipnet_ip_parse_rta_array(nlmsg, IP_NAE_CAPABILITY, sizeof(struct Ip_naemsg));
|
|
if (IP_NULL != caps)
|
|
{
|
|
int i;
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " caps");
|
|
|
|
for (i = 0; IP_NULL != caps[i]; i++)
|
|
{
|
|
struct Ip_rtattr *caps_rta[IP_NAE_CAPABILITY_MAX + 1];
|
|
ipnet_ip_parse_attr(caps_rta, IP_NAE_CAPABILITY_MAX, IP_RTA_DATA(caps[i]), IP_RTA_PAYLOAD(caps[i]));
|
|
|
|
ipnet_ip_stdio_printf(cfg, " %s", ipnet_ip_rta_str(caps_rta[IP_NAE_CAPABILITY_NAME]));
|
|
if (caps_rta[IP_NAE_CAPABILITY_VALUE] != IP_NULL)
|
|
{
|
|
struct Ip_rtattr **caps_v = ipnet_ip_parse_rta_array_nested(caps[i], IP_NAE_CAPABILITY_VALUE);
|
|
if (IP_NULL != caps_v)
|
|
{
|
|
int j;
|
|
for (j = 0; caps_v[j] != IP_NULL; j++)
|
|
ipnet_ip_stdio_printf(cfg, "%s%s", j == 0? "=" : ",", ipnet_ip_rta_str(caps_v[j]));
|
|
}
|
|
|
|
ipcom_free(caps_v);
|
|
}
|
|
}
|
|
|
|
ipcom_free(caps);
|
|
}
|
|
}
|
|
|
|
if (cfg->show_details)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " neigh delete timeout %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_NEIGH_DELETE_TIMEOUT]));
|
|
ipnet_ip_stdio_printf(cfg, " external %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_NEIGH_DELETE_EXTERNAL]));
|
|
ipnet_ip_stdio_printf(cfg, " gc %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_NEIGH_DELETE_GARBAGE_COLLECT]));
|
|
ipnet_ip_stdio_printf(cfg, " flushed %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_NEIGH_DELETE_FLUSHED]));
|
|
ipnet_ip_stdio_printf(cfg, " failed %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_NEIGH_DELETE_FAILED]));
|
|
ipnet_ip_stdio_printf(cfg, " resource %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_NEIGH_DELETE_RESOURCE]));
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " invcalls incomplete %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_INVALID_INCOMPLETE]));
|
|
ipnet_ip_stdio_printf(cfg, " lladdr %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_INVALID_LLADDR]));
|
|
ipnet_ip_stdio_printf(cfg, " delete %d", ipnet_ip_rta_u32(nlmsg->rta[IP_NAE_FWCACHE_INVALID_DELETE]));
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_NAE_PKT_POOL])
|
|
{
|
|
struct Ip_rtattr **pools = ipnet_ip_parse_rta_array(nlmsg, IP_NAE_PKT_POOL, sizeof(struct Ip_naemsg));
|
|
if (IP_NULL != pools)
|
|
{
|
|
int i;
|
|
for (i = 0; IP_NULL != pools[i]; i++)
|
|
{
|
|
struct Ip_rtattr *pool_rta[IP_NAE_PKTPOOL_MAX + 1];
|
|
|
|
ipnet_ip_parse_attr(pool_rta, IP_NAE_PKTPOOL_MAX, IP_RTA_DATA(pools[i]), IP_RTA_PAYLOAD(pools[i]));
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " pool %s", ipnet_ip_rta_str(pool_rta[IP_NAE_PKTPOOL_NAME]));
|
|
ipnet_ip_stdio_printf(cfg, " max %d", ipnet_ip_rta_u32(pool_rta[IP_NAE_PKTPOOL_SIZE]));
|
|
ipnet_ip_stdio_printf(cfg, " avail %d", ipnet_ip_rta_u32(pool_rta[IP_NAE_PKTPOOL_AVAIL]));
|
|
ipnet_ip_stdio_printf(cfg, " mtu %d", ipnet_ip_rta_u32(pool_rta[IP_NAE_PKTPOOL_MTU]));
|
|
ipnet_ip_stdio_printf(cfg, " numa %d", ipnet_ip_rta_u32(pool_rta[IP_NAE_PKTPOOL_NUMA]));
|
|
}
|
|
|
|
ipcom_free(pools);
|
|
}
|
|
}
|
|
}
|
|
|
|
ipnet_ip_stdio_printf(cfg, IP_LF);
|
|
return 0;
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_nae_list(Ipnet_ip_config_t *cfg)
|
|
{
|
|
int ret = 0;
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_naemsg *nae;
|
|
|
|
ipcom_memset(nlh, 0, sizeof(*nlh));
|
|
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
|
|
nlh->nlmsg_type = IP_RTM_GETNAE;
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST;
|
|
|
|
/* Start of the routing message */
|
|
nae = (struct Ip_naemsg *)IP_NLMSG_DATA(nlh);
|
|
ipcom_memset(nae, 0, sizeof(*nae));
|
|
|
|
/* Move past the routing header */
|
|
nlh->nlmsg_len = IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*nae);
|
|
if (cfg->core >= 0)
|
|
{
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump nae information, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int core;
|
|
Ip_bool clear_it = IP_TRUE;
|
|
for (core = 0; core < sizeof(ipcom_nae_shm->fw_map) * 8; core++)
|
|
{
|
|
if (IP_BIT_ISSET(ipcom_nae_shm->fw_map, IP_BIT_VAL(core)))
|
|
{
|
|
ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, core, clear_it);
|
|
clear_it = IP_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
ipnet_cmd_ip_module_nae_print(cfg, nlmsg);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_fwc_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip fwc - Display and modify the IPNET forwarding cache states"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip fwc <list|flush> [dev <devname>] [dst <address>] [hash <id>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip fwc help"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "DESCRIPTION"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " help Display usage information"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " list|flush List/Flush all forwarding entries matching the selectors"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " Selector Decription:"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " hash <id> - The hash index"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " dev <devname> - The forwarding cache must be associated with the device <devname>."IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " dst <address> - The forwarding cache must be associated with destination <address>."IP_LF);
|
|
return ret;
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipnet_cmd_ip_module_fwc_filter(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_fwc_filter_t *filter)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg, *nnlmsg;
|
|
|
|
nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies);
|
|
for ( ; IP_NULL != nlmsg; nlmsg = nnlmsg)
|
|
{
|
|
unsigned i;
|
|
struct Ip_fwcmsg *fwc = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
nnlmsg = IPCOM_LIST_NEXT(&nlmsg->next);
|
|
|
|
if (0 != ipnet_ip_parse_reply(nlmsg, IP_FWC_MAX, sizeof(struct Ip_fwcmsg)))
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
continue;
|
|
}
|
|
|
|
for (i = 0; i < sizeof(filter->mask) * 8; i++)
|
|
{
|
|
if (IP_BIT_ISSET(filter->mask, IP_BIT_UVAL64(i)))
|
|
{
|
|
switch (i)
|
|
{
|
|
case IPNET_IP_FWC_MODIFY_HASH:
|
|
if (filter->hash != fwc->fwc_entry)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
|
|
case IPNET_IP_FWC_MODIFY_DST:
|
|
if (filter->dst.prefix_family != fwc->fwc_family
|
|
|| IP_NULL == nlmsg->rta[IP_FWC_DST])
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
if (IP_FALSE == ipnet_ip_match_prefix(&filter->dst, IP_RTA_DATA(nlmsg->rta[IP_FWC_DST])))
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
break;
|
|
|
|
case IPNET_IP_FWC_MODIFY_DEVNAME:
|
|
if (filter->ifindex != fwc->fwc_index)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
next_message:
|
|
IP_NOOP;
|
|
}
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_fwc_print(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_fwc_filter_t *filter, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
char buf[128];
|
|
|
|
struct Ip_fwcmsg *fwc = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
if (cfg->is_silent)
|
|
return 0;
|
|
|
|
ipnet_ip_parse_reply(nlmsg, IP_FWC_MAX, sizeof(struct Ip_fwcmsg));
|
|
|
|
if (nlmsg->hdr->nlmsg_type == IP_RTM_DELFWCACHE)
|
|
ipnet_ip_stdio_printf(cfg, "Deleted ");
|
|
|
|
ipnet_ip_stdio_printf(cfg, "%s", ipnet_ip_format_host(fwc->fwc_family, IP_RTA_DATA(nlmsg->rta[IP_FWC_DST]), -1, buf, sizeof(buf), "default"));
|
|
ipnet_ip_stdio_printf(cfg, " dev %s", ipnet_ip_if_indextoname(buf, fwc->fwc_index, cfg->vr));
|
|
ipnet_ip_stdio_printf(cfg, " port %u", fwc->fwc_port);
|
|
ipnet_ip_stdio_printf(cfg, " slot %u", fwc->fwc_entry);
|
|
if (cfg->core < 0)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " core %u", fwc->fwc_core);
|
|
ipnet_ip_stdio_printf(cfg, " nae %u", fwc->fwc_nae);
|
|
}
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_FWC_VLAN])
|
|
ipnet_ip_stdio_printf(cfg, " vlan %d", ipnet_ip_rta_u32(nlmsg->rta[IP_FWC_VLAN]));
|
|
|
|
ipnet_ip_stdio_printf(cfg, " lladdr %s", ipnet_ip_format_address(IP_AF_UNSPEC,
|
|
IP_RTA_DATA(nlmsg->rta[IP_FWC_LLADDR]),
|
|
IP_RTA_PAYLOAD(nlmsg->rta[IP_FWC_LLADDR]),
|
|
buf,
|
|
sizeof(buf)));
|
|
|
|
if (IP_GET_32ON8(IP_RTA_DATA(nlmsg->rta[IP_FWC_UNUSED])))
|
|
ipnet_ip_stdio_printf(cfg, " unused");
|
|
|
|
if (fwc->sac_encrypt)
|
|
ipnet_ip_stdio_printf(cfg, " -- IPsec encrypt");
|
|
if (fwc->sac_decrypt)
|
|
ipnet_ip_stdio_printf(cfg, " -- IPsec decrypt");
|
|
|
|
ipnet_ip_stdio_printf(cfg, IP_LF);
|
|
return 0;
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_fwc_listflush(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_fwc_filter_t *filter)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
|
|
/* Time to go through the filter parameters */
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_fwc_modify, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_FWC_MODIFY_HASH:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "hash <id>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&filter->hash, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "hash <id>");
|
|
break;
|
|
|
|
case IPNET_IP_FWC_MODIFY_DST:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dst <address>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(cfg->family, &filter->dst, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dst <address>");
|
|
break;
|
|
|
|
case IPNET_IP_FWC_MODIFY_DEVNAME:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dev <devname>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dev <devname>");
|
|
|
|
/* RESOLVE SPARAM TO IFINDEX */
|
|
filter->ifindex = ipnet_ip_if_nametoindex(sarg, cfg->vr);
|
|
if (-1 == filter->ifindex)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to resolve interface name \'%s\'"IP_LF, sarg);
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* All parameters are parsed
|
|
* Store the argument match mask
|
|
*/
|
|
ipcom_memcpy(&filter->mask, &cfg->mask, sizeof(filter->mask));
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_fwc_list(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ipnet_cmd_ip_module_fwc_filter_t filter;
|
|
int ret = ipnet_cmd_ip_module_fwc_listflush(cfg, &filter);
|
|
|
|
if (0 <= ret)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
|
|
if (cfg->core >= 0)
|
|
{
|
|
/* Dump the NETLINK information */
|
|
if (0 > (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETFWCACHE, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump forwarding cache, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int core;
|
|
Ip_bool clear_it = IP_TRUE;
|
|
for (core = 0; core < sizeof(ipcom_nae_shm->fw_map) * 8; core++)
|
|
{
|
|
if (IP_BIT_ISSET(ipcom_nae_shm->fw_map, IP_BIT_VAL(core)))
|
|
{
|
|
ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETFWCACHE, cfg->family, core, clear_it);
|
|
clear_it = IP_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Filter the reply chain */
|
|
ipnet_cmd_ip_module_fwc_filter(cfg, &filter);
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
ipnet_cmd_ip_module_fwc_print(cfg, &filter, nlmsg);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_fwc_flush(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ipnet_cmd_ip_module_fwc_filter_t filter;
|
|
int ret = ipnet_cmd_ip_module_fwc_listflush(cfg, &filter);
|
|
|
|
if (0 <= ret)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
|
|
/* Dump the NETLINK information */
|
|
if (0 > (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETFWCACHE, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump forwarding cache, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Filter the reply chain */
|
|
ipnet_cmd_ip_module_fwc_filter(cfg, &filter);
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
{
|
|
if (nlmsg->hdr->nlmsg_type != IP_RTM_NEWFWCACHE)
|
|
continue;
|
|
|
|
nlmsg->hdr->nlmsg_type = IP_RTM_DELFWCACHE;
|
|
nlmsg->hdr->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
|
|
ipnet_ip_request_netlink(cfg, cfg->handle, nlmsg->hdr, cfg->core, IP_TRUE);
|
|
ipnet_cmd_ip_module_fwc_print(cfg, &filter, nlmsg);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_IPSEC
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_sac_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip sac - Display and modify the NAE SA cache"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip sac <list|flush> [hash <id>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip sac help"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "DESCRIPTION"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " help Display usage information"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " list|flush List/Flush all SA cache entries matching the selectors"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " Selector Decription:"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " hash <id> - The hash index"IP_LF);
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipnet_cmd_ip_module_sac_filter(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_sac_filter_t *filter)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg, *nnlmsg;
|
|
|
|
nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies);
|
|
for ( ; IP_NULL != nlmsg; nlmsg = nnlmsg)
|
|
{
|
|
unsigned i;
|
|
struct Ip_sacmsg *sac = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
nnlmsg = IPCOM_LIST_NEXT(&nlmsg->next);
|
|
|
|
if (0 != ipnet_ip_parse_reply(nlmsg, IP_SAC_MAX, sizeof(struct Ip_sacmsg)))
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
continue;
|
|
}
|
|
|
|
for (i = 0; i < sizeof(filter->mask) * 8; i++)
|
|
{
|
|
if (IP_BIT_ISSET(filter->mask, IP_BIT_UVAL64(i)))
|
|
{
|
|
switch (i)
|
|
{
|
|
case IPNET_IP_SAC_MODIFY_HASH:
|
|
if (filter->hash != sac->sac_entry)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
next_message:
|
|
IP_NOOP;
|
|
}
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_sac_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
char buf[128];
|
|
struct Ip_sacmsg *sac = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
if (cfg->is_silent)
|
|
return 0;
|
|
|
|
ipnet_ip_parse_reply(nlmsg, IP_SAC_MAX, sizeof(struct Ip_sacmsg));
|
|
|
|
if (nlmsg->hdr->nlmsg_type == IP_RTM_DELSACACHE)
|
|
ipnet_ip_stdio_printf(cfg, "Deleted ");
|
|
|
|
ipnet_ip_stdio_printf(cfg, " src %s", ipnet_ip_format_host(sac->sac_family, IP_RTA_DATA(nlmsg->rta[IP_SAC_SRC]), -1, buf, sizeof(buf), "default"));
|
|
ipnet_ip_stdio_printf(cfg, " dst %s", ipnet_ip_format_host(sac->sac_family, IP_RTA_DATA(nlmsg->rta[IP_SAC_DST]), -1, buf, sizeof(buf), "default"));
|
|
ipnet_ip_stdio_printf(cfg, " alg %s", ipcom_forwarder_ipsec_alg_str(sac->sac_algid));
|
|
ipnet_ip_stdio_printf(cfg, " spi 0x%x", ip_ntohl(sac->sac_spi));
|
|
ipnet_ip_stdio_printf(cfg, " hash %u", sac->sac_entry);
|
|
if (cfg->core < 0)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " core %u", sac->sac_core);
|
|
ipnet_ip_stdio_printf(cfg, " nae %u", sac->sac_nae);
|
|
}
|
|
|
|
ipnet_ip_stdio_printf(cfg, IP_LF);
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_sac_listflush(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_sac_filter_t *filter)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
|
|
/* Time to go through the filter parameters */
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_sac_modify, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_SAC_MODIFY_HASH:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "hash <id>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&filter->hash, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "hash <id>");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* All parameters are parsed
|
|
* Store the argument match mask
|
|
*/
|
|
ipcom_memcpy(&filter->mask, &cfg->mask, sizeof(filter->mask));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_sac_list(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ipnet_cmd_ip_module_sac_filter_t filter;
|
|
int ret = ipnet_cmd_ip_module_sac_listflush(cfg, &filter);
|
|
|
|
if (0 <= ret)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
|
|
if (cfg->core >= 0)
|
|
{
|
|
/* Dump the NETLINK information */
|
|
if (0 > (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETSACACHE, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump SA cache, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int core;
|
|
Ip_bool clear_it = IP_TRUE;
|
|
for (core = 0; core < sizeof(ipcom_nae_shm->fw_map) * 8; core++)
|
|
{
|
|
if (IP_BIT_ISSET(ipcom_nae_shm->fw_map, IP_BIT_VAL(core)))
|
|
{
|
|
ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETSACACHE, cfg->family, core, clear_it);
|
|
clear_it = IP_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Filter the reply chain */
|
|
ipnet_cmd_ip_module_sac_filter(cfg, &filter);
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
ipnet_cmd_ip_module_sac_print(cfg, nlmsg);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_sac_flush(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ipnet_cmd_ip_module_sac_filter_t filter;
|
|
int ret = ipnet_cmd_ip_module_sac_listflush(cfg, &filter);
|
|
|
|
if (0 <= ret)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
|
|
/* Dump the NETLINK information */
|
|
if (0 > (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETSACACHE, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump cache, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Filter the reply chain */
|
|
ipnet_cmd_ip_module_sac_filter(cfg, &filter);
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
{
|
|
if (nlmsg->hdr->nlmsg_type != IP_RTM_NEWSACACHE)
|
|
continue;
|
|
|
|
nlmsg->hdr->nlmsg_type = IP_RTM_DELSACACHE;
|
|
nlmsg->hdr->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
|
|
ipnet_ip_request_netlink(cfg, cfg->handle, nlmsg->hdr, cfg->core, IP_TRUE);
|
|
ipnet_cmd_ip_module_sac_print(cfg, nlmsg);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* IPCOM_USE_FORWARDER_IPSEC */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipnet_cmd_ip_module_fwc(Ipnet_ip_config_t *cfg)
|
|
{
|
|
int arg;
|
|
char *sparam;
|
|
|
|
cfg->handle = ipnet_ip_open_netlink(cfg, 0, IP_NETLINK_ROUTE);
|
|
if (IP_NULL == cfg->handle)
|
|
return -1;
|
|
|
|
/* START */
|
|
|
|
/* Resolve the subcommand */
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sparam, cfg))
|
|
return ipnet_cmd_ip_fwc_usage(cfg, -1);
|
|
|
|
/* Resolve the module */
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_fwc_main, sparam))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
|
|
else
|
|
{
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_FWC_MAIN_LIST:
|
|
return ipnet_cmd_ip_module_fwc_list(cfg);
|
|
case IPNET_IP_FWC_MAIN_FLUSH:
|
|
return ipnet_cmd_ip_module_fwc_flush(cfg);
|
|
case IPNET_IP_FWC_MAIN_HELP:
|
|
return ipnet_cmd_ip_fwc_usage(cfg, 0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef IPCOM_USE_FORWARDER_IPSEC
|
|
IP_GLOBAL int
|
|
ipnet_cmd_ip_module_sac(Ipnet_ip_config_t *cfg)
|
|
{
|
|
int arg;
|
|
char *sparam;
|
|
|
|
cfg->handle = ipnet_ip_open_netlink(cfg, 0, IP_NETLINK_ROUTE);
|
|
if (IP_NULL == cfg->handle)
|
|
return -1;
|
|
|
|
/* START */
|
|
|
|
/* Resolve the subcommand */
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sparam, cfg))
|
|
return ipnet_cmd_ip_sac_usage(cfg, -1);
|
|
|
|
/* Resolve the module */
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_fwc_main, sparam))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
|
|
else
|
|
{
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_SAC_MAIN_LIST:
|
|
return ipnet_cmd_ip_module_sac_list(cfg);
|
|
case IPNET_IP_SAC_MAIN_FLUSH:
|
|
return ipnet_cmd_ip_module_sac_flush(cfg);
|
|
case IPNET_IP_SAC_MAIN_HELP:
|
|
return ipnet_cmd_ip_sac_usage(cfg, 0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipnet_cmd_ip_module_nae(Ipnet_ip_config_t *cfg)
|
|
{
|
|
int arg;
|
|
char *sparam;
|
|
|
|
cfg->handle = ipnet_ip_open_netlink(cfg, 0, IP_NETLINK_ROUTE);
|
|
if (IP_NULL == cfg->handle)
|
|
return -1;
|
|
|
|
/* START */
|
|
|
|
/* Resolve the subcommand */
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sparam, cfg))
|
|
return ipnet_cmd_ip_nae_usage(cfg, -1);
|
|
|
|
/* Resolve the module */
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_nae_main, sparam))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
|
|
else
|
|
{
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_NAE_MAIN_LIST:
|
|
return ipnet_cmd_ip_module_nae_list(cfg);
|
|
case IPNET_IP_NAE_MAIN_HELP:
|
|
return ipnet_cmd_ip_nae_usage(cfg, 0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#endif /* IPNET_USE_NETLINK */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|