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

560 lines
20 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ip_rule.c,v $ $Revision: 1.2.40.3 $
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ip_rule.c,v $
* $Author: hxie $
* $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 IPNET_USE_NETLINK
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
enum
{
IPNET_IP_RULE_MAIN_HELP,
IPNET_IP_RULE_MAIN_LIST,
IPNET_IP_RULE_MAIN_FLUSH,
IPNET_IP_RULE_MAIN_ADD,
IPNET_IP_RULE_MAIN_DEL,
IPNET_IP_RULE_MAIN_MONITOR
};
enum
{
IPNET_IP_RULE_ATTRIBUTE_NOT,
IPNET_IP_RULE_ATTRIBUTE_FROM,
IPNET_IP_RULE_ATTRIBUTE_TO,
IPNET_IP_RULE_ATTRIBUTE_PREFERENCE,
IPNET_IP_RULE_ATTRIBUTE_TABLE,
IPNET_IP_RULE_ATTRIBUTE_IIF,
IPNET_IP_RULE_ATTRIBUTE_PROHIBIT,
IPNET_IP_RULE_ATTRIBUTE_UNREACHABLE,
IPNET_IP_RULE_ATTRIBUTE_REJECT,
IPNET_IP_RULE_ATTRIBUTE_SRCLOOKUP
};
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static Ipcom_cmd_int_str_map ipnet_ip_rule_main[] =
{
{ IPNET_IP_RULE_MAIN_HELP, "help" },
{ IPNET_IP_RULE_MAIN_LIST, "show" },
{ IPNET_IP_RULE_MAIN_LIST, "list" },
{ IPNET_IP_RULE_MAIN_LIST, "lst" },
{ IPNET_IP_RULE_MAIN_FLUSH, "flush" },
{ IPNET_IP_RULE_MAIN_ADD, "add" },
{ IPNET_IP_RULE_MAIN_DEL, "delete" },
{ IPNET_IP_RULE_MAIN_DEL, "del" },
{ IPNET_IP_RULE_MAIN_MONITOR, "monitor" },
{ -1, IP_NULL },
};
static Ipcom_cmd_int_str_map ipnet_ip_rule_attributes[] =
{
{ IPNET_IP_RULE_ATTRIBUTE_NOT, "not" },
{ IPNET_IP_RULE_ATTRIBUTE_FROM, "from" },
{ IPNET_IP_RULE_ATTRIBUTE_TO, "to" },
{ IPNET_IP_RULE_ATTRIBUTE_PREFERENCE, "pref" },
{ IPNET_IP_RULE_ATTRIBUTE_PREFERENCE, "prio" },
{ IPNET_IP_RULE_ATTRIBUTE_PREFERENCE, "priority" },
{ IPNET_IP_RULE_ATTRIBUTE_PREFERENCE, "preference" },
{ IPNET_IP_RULE_ATTRIBUTE_TABLE, "table" },
{ IPNET_IP_RULE_ATTRIBUTE_IIF, "iif" },
{ IPNET_IP_RULE_ATTRIBUTE_PROHIBIT, "prohibit" },
{ IPNET_IP_RULE_ATTRIBUTE_UNREACHABLE, "unreachable" },
{ IPNET_IP_RULE_ATTRIBUTE_REJECT, "reject" },
{ IPNET_IP_RULE_ATTRIBUTE_SRCLOOKUP, "src-lookup" },
{ -1, IP_NULL },
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC int
ipnet_cmd_ip_rule_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 rule - Display and modify the IPNET routing rule states and configurations"IP_LF);
ipnet_ip_stdio_printf(cfg, ""IP_LF);
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
ipnet_ip_stdio_printf(cfg, " ip rule <list|flush>"IP_LF);
ipnet_ip_stdio_printf(cfg, " ip rule <add|del> [not] [from <prefix>] [to <prefix>] [iif <devname>]"IP_LF);
ipnet_ip_stdio_printf(cfg, " [pref <preference>] [table <default|<number>>] [prohibit] [reject] [unreachable] [src-lookup]"IP_LF);
ipnet_ip_stdio_printf(cfg, " ip rule help"IP_LF);
ipnet_ip_stdio_printf(cfg, " ip rule monitor"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 rules"IP_LF);
ipnet_ip_stdio_printf(cfg, " add|delete Add/Delete a rule based on the selectors"IP_LF);
ipnet_ip_stdio_printf(cfg, " Selector Decription:"IP_LF);
ipnet_ip_stdio_printf(cfg, " iif <devname> - The device <devname> the packet was received on"IP_LF);
ipnet_ip_stdio_printf(cfg, " not - The meaning of the rule is inverted"IP_LF);
ipnet_ip_stdio_printf(cfg, " to <prefix> - The prefix matching the destination address"IP_LF);
ipnet_ip_stdio_printf(cfg, " from <prefix> - The prefix matching the source address"IP_LF);
ipnet_ip_stdio_printf(cfg, " table <default|table> - The table to try routing lookup in on success"IP_LF);
ipnet_ip_stdio_printf(cfg, " prohibit - The rule generates a administratively prohibited result"IP_LF);
ipnet_ip_stdio_printf(cfg, " unreachable - The rule generates a network unreachable result"IP_LF);
ipnet_ip_stdio_printf(cfg, " reject - The rule generates a silent drop"IP_LF);
ipnet_ip_stdio_printf(cfg, " pref <preference> - The preference of this rule"IP_LF);
ipnet_ip_stdio_printf(cfg, " src-lookup - Do the routing lookup based on source address"IP_LF);
return ret;
}
IP_STATIC Ip_u32
ipnet_cmd_ip_module_rule_get_table(Ipnet_ip_handle_msg_t *nlmsg)
{
struct Ip_fib_rule_hdr *fib = IP_NLMSG_DATA(nlmsg->hdr);
if (nlmsg->rta[IP_FRA_TABLE])
return ipnet_ip_rta_u32(nlmsg->rta[IP_FRA_TABLE]);
return fib->table;
}
IP_STATIC int
ipnet_cmd_ip_module_rule_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
{
char buf[128];
struct Ip_fib_rule_hdr *fib = IP_NLMSG_DATA(nlmsg->hdr);
if (cfg->is_silent)
return 0;
ipnet_ip_parse_reply(nlmsg, IP_FRA_MAX, sizeof(*fib));
if (nlmsg->hdr->nlmsg_type == IP_RTM_DELRULE)
ipnet_ip_stdio_printf(cfg, "Deleted ");
ipcom_snprintf(buf, sizeof(buf), "%u:", IP_NULL != nlmsg->rta[IP_FRA_PRIORITY]? ipnet_ip_rta_u32(nlmsg->rta[IP_FRA_PRIORITY]) : 0);
ipnet_ip_stdio_printf(cfg, "%08s", buf);
if (IP_BIT_ISSET(fib->flags, IP_FIB_RULE_INVERT))
ipnet_ip_stdio_printf(cfg, " not");
ipnet_ip_stdio_printf(cfg, " from %s", ipnet_ip_format_host(fib->family, ipnet_ip_rta_data_safe(nlmsg->rta[IP_FRA_SRC]), fib->src_len, buf, sizeof(buf), "all"));
ipnet_ip_stdio_printf(cfg, " to %s", ipnet_ip_format_host(fib->family, ipnet_ip_rta_data_safe(nlmsg->rta[IP_FRA_DST]), fib->dst_len, buf, sizeof(buf), "all"));
if (IP_NULL != nlmsg->rta[IP_FRA_IFNAME])
ipnet_ip_stdio_printf(cfg, " iif %s", ipnet_ip_rta_str(nlmsg->rta[IP_FRA_IFNAME]));
if (IP_FR_ACT_TO_TBL == fib->action)
ipnet_ip_stdio_printf(cfg, " table %u", ipnet_cmd_ip_module_rule_get_table(nlmsg));
else if (IP_FR_ACT_BLACKHOLE == fib->action)
ipnet_ip_stdio_printf(cfg, " reject");
else if (IP_FR_ACT_UNREACHABLE == fib->action)
ipnet_ip_stdio_printf(cfg, " unreachable");
else if (IP_FR_ACT_PROHIBIT == fib->action)
ipnet_ip_stdio_printf(cfg, " prohibit");
if (IP_BIT_ISSET(fib->flags, IP_FIB_RULE_FIND_SADDR))
ipnet_ip_stdio_printf(cfg, " src-lookup");
ipnet_ip_stdio_printf(cfg, IP_LF);
return 0;
}
IP_STATIC Ip_ssize_t
ipnet_cmd_ip_module_rule_list(Ipnet_ip_config_t *cfg)
{
Ip_ssize_t ret;
Ipnet_ip_handle_msg_t *nlmsg;
/* Dump the NETLINK information */
if (0 <= (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETRULE, cfg->family, cfg->core, IP_TRUE)))
{
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
ipnet_cmd_ip_module_rule_print(cfg, nlmsg);
}
else
ipnet_ip_stdio_printf(cfg, "Unable to dump rule table, error = %d"IP_LF, (int)ret);
return ret;
}
IP_STATIC Ip_ssize_t
ipnet_cmd_ip_module_rule_flush(Ipnet_ip_config_t *cfg)
{
Ip_ssize_t ret;
Ipnet_ip_handle_msg_t *nlmsg;
/* Dump the NETLINK information */
if (0 <= (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_RTM_GETRULE, cfg->family, cfg->core, IP_TRUE)))
{
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
{
if (nlmsg->hdr->nlmsg_type != IP_RTM_NEWRULE)
continue;
nlmsg->hdr->nlmsg_type = IP_RTM_DELRULE;
nlmsg->hdr->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
(void)ipnet_ip_request_netlink(cfg, cfg->handle, nlmsg->hdr, cfg->core, IP_TRUE);
ipnet_cmd_ip_module_rule_print(cfg, nlmsg);
}
}
return 0;
}
IP_STATIC Ip_ssize_t
ipnet_cmd_ip_module_rule_modify(Ipnet_ip_config_t *cfg)
{
char *sarg;
int arg;
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
struct Ip_fib_rule_hdr *fib;
Ip_u32 uarg;
ipcom_memset(nlh, 0, sizeof(*nlh));
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
/* Start of the routing message */
fib = (struct Ip_fib_rule_hdr *)IP_NLMSG_DATA(nlh);
ipcom_memset(fib, 0, sizeof(*fib));
fib->family = cfg->family;
/* Move past the routing header */
nlh->nlmsg_len = IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*fib);
/* Time to go through the filter parameters */
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
{
Ipnet_ip_prefix_t addr;
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_rule_attributes, sarg))
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
switch (arg)
{
case IPNET_IP_RULE_ATTRIBUTE_NOT:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "not", arg))
return -1;
fib->flags |= IP_FIB_RULE_INVERT;
break;
case IPNET_IP_RULE_ATTRIBUTE_SRCLOOKUP:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "src-lookup", arg))
return -1;
fib->flags |= IP_FIB_RULE_FIND_SADDR;
break;
case IPNET_IP_RULE_ATTRIBUTE_FROM:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "from <prefix>", arg))
return -1;
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
return ipnet_cmd_ip_requires_argument(cfg, "from <prefix>");
if (IP_TRUE != ipnet_ip_str_to_prefix(fib->family, sarg, &addr))
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
if (fib->family == IP_AF_UNSPEC)
fib->family = addr.prefix_family;
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_FRA_SRC, &addr.prefix, addr.prefix_max/8);
fib->src_len = addr.prefix_length;
break;
case IPNET_IP_RULE_ATTRIBUTE_TO:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "to <prefix>", arg))
return -1;
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
return ipnet_cmd_ip_requires_argument(cfg, "to <prefix>");
if (IP_TRUE != ipnet_ip_str_to_prefix(fib->family, sarg, &addr))
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
if (fib->family == IP_AF_UNSPEC)
fib->family = addr.prefix_family;
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_FRA_DST, &addr.prefix, addr.prefix_max/8);
fib->dst_len = addr.prefix_length;
break;
case IPNET_IP_RULE_ATTRIBUTE_PREFERENCE:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "pref <preference>", arg))
return -1;
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
return ipnet_cmd_ip_requires_argument(cfg, "scope <scope>");
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_FRA_PRIORITY, &uarg, sizeof(uarg));
break;
case IPNET_IP_RULE_ATTRIBUTE_TABLE:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "table <table>", arg))
return -1;
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
return ipnet_cmd_ip_requires_argument(cfg, "table <table>");
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_FRA_TABLE, &uarg, sizeof(uarg));
fib->table = (Ip_u16)uarg;
fib->action = IP_FR_ACT_TO_TBL;
break;
case IPNET_IP_RULE_ATTRIBUTE_PROHIBIT:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "prohibit", arg))
return -1;
fib->action = IP_FR_ACT_PROHIBIT;
break;
case IPNET_IP_RULE_ATTRIBUTE_UNREACHABLE:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "unreachable", arg))
return -1;
fib->action = IP_FR_ACT_UNREACHABLE;
break;
case IPNET_IP_RULE_ATTRIBUTE_REJECT:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "reject", arg))
return -1;
fib->action = IP_FR_ACT_BLACKHOLE;
break;
case IPNET_IP_RULE_ATTRIBUTE_IIF:
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "iif <devname>", arg))
return -1;
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
return ipnet_cmd_ip_requires_argument(cfg, "iif <devname>");
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_FRA_IFNAME, sarg, ipcom_strlen(sarg) + 1);
break;
}
}
if (fib->action == IP_FR_ACT_UNSPEC)
{
ipnet_ip_stdio_printf(cfg, "One of \'table <table>\', \'reject\', \'prohibit\' or \'unreachable\' must be specified"IP_LF);
return -1;
}
if (fib->family == IP_AF_UNSPEC)
{
if (cfg->family != IP_AF_UNSPEC)
fib->family = cfg->family;
else
{
#if defined(IPCOM_USE_INET)
fib->family = IP_AF_INET;
#else
fib->family = IP_AF_INET6;
#endif
}
}
return 0;
}
IP_STATIC Ip_ssize_t
ipnet_cmd_ip_module_rule_add(Ipnet_ip_config_t *cfg)
{
Ip_ssize_t ret = ipnet_cmd_ip_module_rule_modify(cfg);
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
if (0 <= ret)
{
nlh->nlmsg_flags = IP_NLM_F_CREATE|IP_NLM_F_EXCL|IP_NLM_F_REQUEST|IP_NLM_F_ACK;
nlh->nlmsg_type = IP_RTM_NEWRULE;
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
ipnet_ip_stdio_printf(cfg, "RTNETLINK answers: %s"IP_LF, ipcom_strerror(-(int)ret));
}
return ret;
}
IP_STATIC Ip_ssize_t
ipnet_cmd_ip_module_rule_delete(Ipnet_ip_config_t *cfg)
{
Ip_ssize_t ret = ipnet_cmd_ip_module_rule_modify(cfg);
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
if (0 <= ret)
{
nlh->nlmsg_type = IP_RTM_DELRULE;
nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
ipnet_ip_stdio_printf(cfg, "RTNETLINK answers: %s"IP_LF, ipcom_strerror(-(int)ret));
}
return ret;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_ssize_t
ipnet_cmd_ip_module_rule(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_rule_usage(cfg, -1);
/* Resolve the module */
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_rule_main, sparam))
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
else
{
ipnet_cmd_ip_clear_mask(cfg);
switch (arg)
{
case IPNET_IP_RULE_MAIN_ADD:
return ipnet_cmd_ip_module_rule_add(cfg);
case IPNET_IP_RULE_MAIN_DEL:
return ipnet_cmd_ip_module_rule_delete(cfg);
case IPNET_IP_RULE_MAIN_LIST:
return ipnet_cmd_ip_module_rule_list(cfg);
case IPNET_IP_RULE_MAIN_FLUSH:
return ipnet_cmd_ip_module_rule_flush(cfg);
case IPNET_IP_RULE_MAIN_HELP:
return ipnet_cmd_ip_rule_usage(cfg, 0);
case IPNET_IP_RULE_MAIN_MONITOR:
return ipnet_cmd_ip_module_monitor(cfg, IP_BIT_VAL(IPNET_IP_MODULE_RULE));
}
}
return 0;
}
IP_GLOBAL Ip_u32
ipnet_cmd_ip_module_rule_monitor_groups(Ipnet_ip_config_t *cfg)
{
if (cfg->family == IP_AF_INET)
return IP_RTMGRP_IPV4_RULE;
if (cfg->family == IP_AF_INET6)
return IP_RTMGRP_IPV6_RULE;
return IP_RTMGRP_IPV6_RULE|IP_RTMGRP_IPV4_RULE;
}
IP_GLOBAL Ip_bool
ipnet_cmd_ip_module_rule_monitor(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
{
if (nlmsg->hdr->nlmsg_type == IP_RTM_NEWRULE || nlmsg->hdr->nlmsg_type == IP_RTM_DELRULE)
{
ipnet_cmd_ip_module_rule_print(cfg, nlmsg);
return IP_TRUE;
}
return IP_FALSE;
}
IP_GLOBAL Ip_ssize_t
ipnet_cmd_ip_module_rule_flush_all(Ipnet_ip_config_t *cfg)
{
/**/
return ipnet_cmd_ip_module_rule_flush(cfg);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#endif /* IPNET_USE_NETLINK */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/