1968 lines
77 KiB
C
1968 lines
77 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ip_link.c,v $ $Revision: 1.4.12.4 $
|
|
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ip_link.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_LINK_MAIN_HELP,
|
|
IPNET_IP_LINK_MAIN_LIST,
|
|
IPNET_IP_LINK_MAIN_FLUSH,
|
|
IPNET_IP_LINK_MAIN_ADD,
|
|
IPNET_IP_LINK_MAIN_SET,
|
|
IPNET_IP_LINK_MAIN_DEL,
|
|
IPNET_IP_LINK_MAIN_REPLACE,
|
|
IPNET_IP_LINK_MAIN_MONITOR
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_LINK_ATTRIBUTE_DEVNAME,
|
|
IPNET_IP_LINK_ATTRIBUTE_UP,
|
|
IPNET_IP_LINK_ATTRIBUTE_DOWN,
|
|
IPNET_IP_LINK_ATTRIBUTE_TYPE,
|
|
IPNET_IP_LINK_ATTRIBUTE_LINK,
|
|
IPNET_IP_LINK_ATTRIBUTE_NAME,
|
|
IPNET_IP_LINK_ATTRIBUTE_MTU,
|
|
IPNET_IP_LINK_ATTRIBUTE_MULTICAST,
|
|
IPNET_IP_LINK_ATTRIBUTE_ALLMULTI,
|
|
IPNET_IP_LINK_ATTRIBUTE_PROMISC,
|
|
IPNET_IP_LINK_ATTRIBUTE_ADDRESS,
|
|
IPNET_IP_LINK_ATTRIBUTE_BROADCAST,
|
|
IPNET_IP_LINK_ATTRIBUTE_VR,
|
|
IPNET_IP_LINK_ATTRIBUTE_NOOP,
|
|
IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG,
|
|
IPNET_IP_LINK_ATTRIBUTE_HELP
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_LINK_VLAN_ATTRIBUTE_ID,
|
|
IPNET_IP_LINK_VLAN_ATTRIBUTE_DEVNAME,
|
|
IPNET_IP_LINK_VLAN_ATTRIBUTE_EQM,
|
|
IPNET_IP_LINK_VLAN_ATTRIBUTE_IQM
|
|
};
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
enum
|
|
{
|
|
IPNET_IP_LINK_NAE_RESET
|
|
};
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
typedef struct Ipnet_cmd_ip_module_link_filter_struct
|
|
{
|
|
Ip_u64 mask;
|
|
|
|
Ip_u32 ifindex;
|
|
char type[64];
|
|
} Ipnet_cmd_ip_module_link_filter_t;
|
|
|
|
typedef struct Ipnet_ip_link_type_map_struct
|
|
{
|
|
int type;
|
|
int family;
|
|
} Ipnet_ip_link_type_map;
|
|
|
|
|
|
typedef void (*Ipnet_ip_link_info_print_t) (Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev);
|
|
typedef int (*Ipnet_ip_link_info_parse_t) (Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev);
|
|
typedef void (*Ipnet_ip_link_info_help_t) (Ipnet_ip_config_t *cfg);
|
|
|
|
typedef struct Ipnet_ip_link_info_struct
|
|
{
|
|
char *kind;
|
|
Ipnet_ip_link_info_print_t print_linkinfo;
|
|
Ipnet_ip_link_info_parse_t parse_linkinfo;
|
|
Ipnet_ip_link_info_help_t help_linkinfo;
|
|
} Ipnet_ip_link_info_map;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
IP_STATIC int ipnet_cmd_ip_link_usage(Ipnet_ip_config_t *cfg, int ret);
|
|
|
|
IP_STATIC void ipnet_ip_link_info_vlan_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev);
|
|
IP_STATIC int ipnet_ip_link_info_vlan_parse(Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev);
|
|
IP_STATIC void ipnet_ip_link_info_vlan_help(Ipnet_ip_config_t *cfg);
|
|
|
|
IP_STATIC void ipnet_ip_link_info_tunnel_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev);
|
|
IP_STATIC int ipnet_ip_link_info_tunnel_parse(Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev);
|
|
IP_STATIC void ipnet_ip_link_info_tunnel_help(Ipnet_ip_config_t *cfg);
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
IP_STATIC void ipnet_ip_link_info_nae_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev);
|
|
IP_STATIC int ipnet_ip_link_info_nae_parse(Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev);
|
|
IP_STATIC void ipnet_ip_link_info_nae_help(Ipnet_ip_config_t *cfg);
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_main[] =
|
|
{
|
|
{ IPNET_IP_LINK_MAIN_HELP, "help" },
|
|
|
|
{ IPNET_IP_LINK_MAIN_LIST, "show" },
|
|
{ IPNET_IP_LINK_MAIN_LIST, "list" },
|
|
{ IPNET_IP_LINK_MAIN_LIST, "lst" },
|
|
{ IPNET_IP_LINK_MAIN_LIST, "get" },
|
|
{ IPNET_IP_LINK_MAIN_FLUSH, "flush" },
|
|
|
|
{ IPNET_IP_LINK_MAIN_ADD, "add" },
|
|
{ IPNET_IP_LINK_MAIN_DEL, "delete" },
|
|
{ IPNET_IP_LINK_MAIN_DEL, "del" },
|
|
{ IPNET_IP_LINK_MAIN_SET, "set" },
|
|
{ IPNET_IP_LINK_MAIN_SET, "change" },
|
|
{ IPNET_IP_LINK_MAIN_SET, "chg" },
|
|
{ IPNET_IP_LINK_MAIN_REPLACE, "replace" },
|
|
{ IPNET_IP_LINK_MAIN_MONITOR, "monitor" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_type[] =
|
|
{
|
|
{ IP_ARPHRD_ETHER, "ether" },
|
|
{ IP_ARPHRD_TUNNEL, "ipip" },
|
|
{ IP_ARPHRD_LOOPBACK, "loopback" },
|
|
{ IP_ARPHRD_VOID, "void" },
|
|
{ IP_ARPHRD_PPP, "ppp" },
|
|
{ IP_ARPHRD_IEEE80211, "ieee802.11" },
|
|
{ IP_ARPHRD_SIT, "sit" },
|
|
{ IP_ARPHRD_TUNNEL6, "tunnel6" },
|
|
{ IP_ARPHRD_IPGRE, "gre" },
|
|
{ IP_ARPHRD_NONE, "none" },
|
|
{ IP_ARPHRD_TUNNEL6TO4, "tunnel6to4" },
|
|
{ IP_ARPHRD_IPGRE6, "gre6" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_tunnel_type[] =
|
|
{
|
|
{ IP_ARPHRD_TUNNEL, "ipip" },
|
|
{ IP_ARPHRD_SIT, "sit" },
|
|
{ IP_ARPHRD_TUNNEL6, "ip6ip6" },
|
|
{ IP_ARPHRD_TUNNEL6, "tunnel6" },
|
|
{ IP_ARPHRD_IPGRE, "gre" },
|
|
{ IP_ARPHRD_TUNNEL6TO4, "6to4" },
|
|
{ IP_ARPHRD_TUNNEL6TO4, "tunnel6to4" },
|
|
{ IP_ARPHRD_IPGRE6, "gre6" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
|
|
static Ipnet_ip_link_type_map ipnet_ip_link_type_map[] =
|
|
{
|
|
{ IP_ARPHRD_ETHER, IP_AF_UNSPEC },
|
|
{ IP_ARPHRD_TUNNEL, IP_AF_INET },
|
|
{ IP_ARPHRD_LOOPBACK, IP_AF_UNSPEC },
|
|
{ IP_ARPHRD_VOID, IP_AF_UNSPEC },
|
|
{ IP_ARPHRD_PPP, IP_AF_UNSPEC },
|
|
{ IP_ARPHRD_IEEE80211, IP_AF_UNSPEC },
|
|
{ IP_ARPHRD_SIT, IP_AF_INET },
|
|
{ IP_ARPHRD_TUNNEL6, IP_AF_INET6 },
|
|
{ IP_ARPHRD_IPGRE, IP_AF_INET },
|
|
{ IP_ARPHRD_NONE, IP_AF_UNSPEC },
|
|
{ IP_ARPHRD_TUNNEL6TO4, IP_AF_INET6 },
|
|
{ IP_ARPHRD_IPGRE6, IP_AF_INET6 },
|
|
|
|
{ -1, -1 }
|
|
};
|
|
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_attributes[] =
|
|
{
|
|
{ IPNET_IP_LINK_ATTRIBUTE_DEVNAME, "dev" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_UP, "up" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_DOWN, "down" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_TYPE, "type" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_LINK, "link" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_NAME, "name" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_MTU, "mtu" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_ADDRESS, "address" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_BROADCAST, "broadcast" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_MULTICAST, "multicast" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_ALLMULTI, "allmulticast"},
|
|
{ IPNET_IP_LINK_ATTRIBUTE_PROMISC, "promisc" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_HELP, "help" },
|
|
|
|
{ IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG, "txqueuelen" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG, "netns" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG, "trailers" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG, "arp" },
|
|
{ IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG, "dynamic" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_vlan_attributes[] =
|
|
{
|
|
{ IPNET_IP_LINK_VLAN_ATTRIBUTE_ID, "id" },
|
|
{ IPNET_IP_LINK_VLAN_ATTRIBUTE_DEVNAME, "dev" },
|
|
|
|
|
|
{ IPNET_IP_LINK_VLAN_ATTRIBUTE_EQM, "egress-qos-map" },
|
|
{ IPNET_IP_LINK_VLAN_ATTRIBUTE_IQM, "ingress-qos-map"},
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_DEVNAME,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_MODE,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_LOCAL,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_REMOTE,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_KEY,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_IKEY,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_OKEY,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_ISEQ,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_NISEQ,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_OSEQ,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_NOSEQ,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_SEQ,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_NSEQ,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_ICSUM,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_NICSUM,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_OCSUM,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_NOCSUM,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_CSUM,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_NCSUM,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_TTL,
|
|
IPNET_IP_TUNNEL_ATTRIBUTE_HELP
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_tunnel_attributes[] =
|
|
{
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_DEVNAME, "dev" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_MODE, "mode" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_LOCAL, "local" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_REMOTE, "remote" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_IKEY, "key" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_IKEY, "ikey" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_OKEY, "okey" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_ISEQ, "iseq" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_NISEQ, "-iseq" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_OSEQ, "oseq" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_NOSEQ, "-oseq" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_SEQ, "seq" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_NSEQ, "-seq" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_ICSUM, "icsum" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_NICSUM, "-icsum" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_OCSUM, "ocsum" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_NOCSUM, "-ocsum" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_CSUM, "csum" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_NCSUM, "-csum" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_TTL, "ttl" },
|
|
{ IPNET_IP_TUNNEL_ATTRIBUTE_HELP, "help" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
static Ipcom_cmd_int_str_map ipnet_ip_link_nae_attributes[] =
|
|
{
|
|
{ IPNET_IP_LINK_NAE_RESET, "reset" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
#endif
|
|
|
|
static Ipnet_ip_link_info_map ipnet_ip_link_info_map[] =
|
|
{
|
|
{ "vlan", ipnet_ip_link_info_vlan_print, ipnet_ip_link_info_vlan_parse, ipnet_ip_link_info_vlan_help },
|
|
{ "tunnel", ipnet_ip_link_info_tunnel_print, ipnet_ip_link_info_tunnel_parse, ipnet_ip_link_info_tunnel_help },
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
{ "nae", ipnet_ip_link_info_nae_print, ipnet_ip_link_info_nae_parse, ipnet_ip_link_info_nae_help },
|
|
#endif
|
|
|
|
{ IP_NULL, IP_NULL, IP_NULL, IP_NULL }
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* IPLINK - NAE
|
|
****************************************************************************
|
|
*/
|
|
#if defined(IPCOM_FORWARDER_NAE)
|
|
IP_STATIC void
|
|
ipnet_ip_link_info_nae_help(Ipnet_ip_config_t *cfg)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " nae reset"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " reset - Reset statistics for this NAE interface"IP_LF);
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipnet_ip_link_info_nae_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev)
|
|
{
|
|
(void) cfg;
|
|
(void) nlmsg;
|
|
(void) dev;
|
|
|
|
if (IP_NULL != link_info)
|
|
{
|
|
struct Ip_rtattr *vattr[IP_IFPROXY_MAX + 1];
|
|
struct Ip_rtattr *attr = IP_RTA_DATA(link_info);
|
|
Ip_size_t attrlen = IP_RTA_PAYLOAD(link_info);
|
|
|
|
ipnet_ip_parse_attr(vattr, IP_IFPROXY_MAX, attr, attrlen);
|
|
|
|
if (IP_NULL != vattr[IP_IFPROXY_IFNAME])
|
|
ipnet_ip_stdio_printf(cfg, " end %s", ipnet_ip_rta_str(vattr[IP_IFPROXY_IFNAME]));
|
|
|
|
if (IP_NULL != vattr[IP_IFPROXY_PORT_INDEX])
|
|
ipnet_ip_stdio_printf(cfg, " port %u", ipnet_ip_rta_u32(vattr[IP_IFPROXY_PORT_INDEX]));
|
|
|
|
if (IP_NULL != vattr[IP_IFPROXY_MIPC_PORT])
|
|
ipnet_ip_stdio_printf(cfg, " mipc %u", ipnet_ip_rta_u32(vattr[IP_IFPROXY_MIPC_PORT]));
|
|
|
|
if (IP_NULL != vattr[IP_IFPROXY_CORES])
|
|
{
|
|
Ip_u64 cores;
|
|
ipcom_memcpy(&cores, IP_RTA_DATA(vattr[IP_IFPROXY_CORES]), sizeof(cores));
|
|
|
|
ipnet_ip_stdio_printf(cfg, " cores ");
|
|
if (0 == cores)
|
|
ipnet_ip_stdio_printf(cfg, "none");
|
|
else
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(cores) * 8; i++)
|
|
{
|
|
if (IP_BIT_ISSET(cores, IP_BIT_VAL(i)))
|
|
{
|
|
IP_BIT_CLR(cores, IP_BIT_VAL(i));
|
|
ipnet_ip_stdio_printf(cfg, "%d%s", i, cores? "," : "");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != cfg->show_stats && IP_NULL != vattr[IP_IFPROXY_STATS_DRIVER])
|
|
{
|
|
struct Ip_rtnl_link_stats64 stack_stats;
|
|
struct Ip_rtnl_link_stats64 total_stats;
|
|
|
|
ipcom_memcpy(&stack_stats, IP_RTA_DATA(vattr[IP_IFPROXY_STATS_STACK]), sizeof(stack_stats));
|
|
ipcom_memcpy(&total_stats, IP_RTA_DATA(vattr[IP_IFPROXY_STATS_DRIVER]), sizeof(total_stats));
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " NAE RX: layer %-10s %-8s %-8s %-8s",
|
|
"bytes", "packets", "mgmt", "dropped");
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
|
|
ipnet_ip_stdio_printf(cfg, " stack %-10llu %-8llu %-8llu %-8llu",
|
|
(unsigned long long)stack_stats.rx_bytes, (unsigned long long)stack_stats.rx_packets, (unsigned long long)stack_stats.rx_errors, (unsigned long long)stack_stats.rx_dropped);
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " driver %-10llu %-8llu %-8llu %-8llu",
|
|
(unsigned long long)total_stats.rx_bytes, (unsigned long long)total_stats.rx_packets, (unsigned long long)total_stats.rx_errors, (unsigned long long)total_stats.rx_dropped);
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
|
|
ipnet_ip_stdio_printf(cfg, " NAE TX: layer %-10s %-8s %-8s %-8s",
|
|
"bytes", "packets", "neigh", "dropped");
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " stack %-10llu %-8llu %-8llu %-8llu",
|
|
(unsigned long long)stack_stats.tx_bytes, (unsigned long long)stack_stats.tx_packets, (unsigned long long)stack_stats.tx_errors, (unsigned long long)stack_stats.tx_dropped);
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " driver %-10llu %-8llu %-8llu %-8llu",
|
|
(unsigned long long)total_stats.tx_bytes, (unsigned long long)total_stats.tx_packets, (unsigned long long)total_stats.tx_errors, (unsigned long long)total_stats.tx_dropped);
|
|
}
|
|
}
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_ip_link_info_nae_parse(Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
Ip_u32 uarg;
|
|
|
|
if (ifla_dev != IP_NULL)
|
|
return -1;
|
|
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
/* 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_link_nae_attributes, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_LINK_NAE_RESET:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "reset", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFPROXY_RESET, &uarg, sizeof(uarg));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
/*
|
|
****************************************************************************
|
|
* IPLINK - VLAN
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC void
|
|
ipnet_ip_link_info_vlan_help(Ipnet_ip_config_t *cfg)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " vlan [id <vlan_id>] [egress-qos-map <from:to>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " id <vlan_id> - VLAN ID for this interface"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " egress-qos-map <from:to> - To is VLAN priority <0-7>. From is traffic class number"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ingress-qos-map <from:to> - From is VLAN priority<0-7>. To is traffic class number"IP_LF);
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipnet_ip_link_info_vlan_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev)
|
|
{
|
|
(void) cfg;
|
|
(void) nlmsg;
|
|
|
|
if (IP_NULL != dev)
|
|
ipnet_ip_stdio_printf(cfg, "%s:", dev);
|
|
|
|
if (IP_NULL != link_info)
|
|
{
|
|
struct Ip_rtattr *vattr[IP_IFLA_VLAN_MAX + 1];
|
|
struct Ip_rtattr *attr = IP_RTA_DATA(link_info);
|
|
Ip_size_t attrlen = IP_RTA_PAYLOAD(link_info);
|
|
|
|
ipnet_ip_parse_attr(vattr, IP_IFLA_VLAN_MAX, attr, attrlen);
|
|
|
|
if (IP_NULL != vattr[IP_IFLA_VLAN_ID])
|
|
ipnet_ip_stdio_printf(cfg, " id %u", ipnet_ip_rta_u16(vattr[IP_IFLA_VLAN_ID]));
|
|
|
|
if (IP_NULL != vattr[IP_IFLA_VLAN_EGRESS_QOS])
|
|
{
|
|
struct Ip_rtattr *rta = IP_RTA_DATA(vattr[IP_IFLA_VLAN_EGRESS_QOS]);
|
|
Ip_size_t rtalen = IP_RTA_PAYLOAD(vattr[IP_IFLA_VLAN_EGRESS_QOS]);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " egress-qos-map { ");
|
|
while (IP_RTA_OK(rta, rtalen))
|
|
{
|
|
struct Ip_ifla_vlan_qos_mapping vmap;
|
|
|
|
ipcom_memcpy(&vmap, IP_RTA_DATA(rta), sizeof(vmap));
|
|
ipnet_ip_stdio_printf(cfg, "%u:%u ", vmap.from, vmap.to);
|
|
rta = IP_RTA_NEXT(rta, rtalen);
|
|
}
|
|
|
|
ipnet_ip_stdio_printf(cfg, "}");
|
|
}
|
|
|
|
if (IP_NULL != vattr[IP_IFLA_VLAN_INGRESS_QOS])
|
|
{
|
|
struct Ip_rtattr *rta = IP_RTA_DATA(vattr[IP_IFLA_VLAN_INGRESS_QOS]);
|
|
Ip_size_t rtalen = IP_RTA_PAYLOAD(vattr[IP_IFLA_VLAN_INGRESS_QOS]);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " ingress-qos-map { ");
|
|
while (IP_RTA_OK(rta, rtalen))
|
|
{
|
|
struct Ip_ifla_vlan_qos_mapping vmap;
|
|
|
|
ipcom_memcpy(&vmap, IP_RTA_DATA(rta), sizeof(vmap));
|
|
ipnet_ip_stdio_printf(cfg, "%u:%u ", vmap.from, vmap.to);
|
|
rta = IP_RTA_NEXT(rta, rtalen);
|
|
}
|
|
|
|
ipnet_ip_stdio_printf(cfg, "}");
|
|
}
|
|
}
|
|
}
|
|
|
|
IP_STATIC Ip_bool
|
|
ipnet_ip_link_info_vlan_parse_qos_map(Ipnet_ip_config_t *cfg, const char *str, struct Ip_ifla_vlan_qos_mapping *vmap)
|
|
{
|
|
char *sto;
|
|
char buf[64];
|
|
Ip_u32 uarg;
|
|
|
|
ipcom_strncpy(buf, str, sizeof(buf));
|
|
buf[sizeof(buf)-1] = '\0';
|
|
|
|
if (IP_NULL == (sto = ipcom_strchr(buf, ':')))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "QOS MAP syntax is from:to <%s>"IP_LF, str, buf);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
*sto++ = '\0';
|
|
|
|
if (!ipnet_ip_str_to_uint(&uarg, buf, IP_NULL))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to parse QOS MAP %s [%s]"IP_LF, str, buf);
|
|
return IP_FALSE;
|
|
}
|
|
vmap->from = uarg;
|
|
|
|
if (!ipnet_ip_str_to_uint(&uarg, sto, IP_NULL))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to parse QOS MAP %s [%s]"IP_LF, str, buf);
|
|
return IP_FALSE;
|
|
}
|
|
vmap->to = uarg;
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_ip_link_info_vlan_parse(Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
Ip_u16 uarg16;
|
|
struct Ip_ifla_vlan_qos_mapping vmap;
|
|
char emapbuf[64];
|
|
char imapbuf[64];
|
|
struct Ip_rtattr *egress = (struct Ip_rtattr *)emapbuf;
|
|
struct Ip_rtattr *ingress = (struct Ip_rtattr *)imapbuf;
|
|
|
|
egress->rta_type = IP_IFLA_VLAN_EGRESS_QOS;
|
|
egress->rta_len = IP_RTA_LENGTH(0);
|
|
|
|
ingress->rta_type = IP_IFLA_VLAN_INGRESS_QOS;
|
|
ingress->rta_len = IP_RTA_LENGTH(0);
|
|
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
/* 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_link_vlan_attributes, sarg))
|
|
{
|
|
if (IP_NULL != ifla_dev && IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_LINK_VLAN_ATTRIBUTE_DEVNAME)))
|
|
{
|
|
(void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_LINK_VLAN_ATTRIBUTE_DEVNAME);
|
|
*ifla_dev = sarg;
|
|
continue;
|
|
}
|
|
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
}
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_LINK_VLAN_ATTRIBUTE_DEVNAME:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dev <devname>", arg))
|
|
return -1;
|
|
|
|
if (IP_NULL == ifla_dev)
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dev <devname>");
|
|
|
|
*ifla_dev = sarg;
|
|
break;
|
|
case IPNET_IP_LINK_VLAN_ATTRIBUTE_ID:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "id <vlan_id>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_ushort(&uarg16, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "id <vlan_id>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_VLAN_ID, &uarg16, sizeof(uarg16));
|
|
break;
|
|
case IPNET_IP_LINK_VLAN_ATTRIBUTE_EQM:
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "egress-qos-map <from:to>");
|
|
|
|
if (!ipnet_ip_link_info_vlan_parse_qos_map(cfg, sarg, &vmap))
|
|
return -1;
|
|
ipcom_netlink_rta_addattr_l(egress, sizeof(emapbuf), IP_IFLA_VLAN_QOS_MAPPING, &vmap, sizeof(vmap));
|
|
break;
|
|
case IPNET_IP_LINK_VLAN_ATTRIBUTE_IQM:
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "ingress-qos-map <from:to>");
|
|
|
|
if (!ipnet_ip_link_info_vlan_parse_qos_map(cfg, sarg, &vmap))
|
|
return -1;
|
|
|
|
ipcom_netlink_rta_addattr_l(ingress, sizeof(imapbuf), IP_IFLA_VLAN_QOS_MAPPING, &vmap, sizeof(vmap));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (egress->rta_len != IP_RTA_LENGTH(0))
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_VLAN_EGRESS_QOS, IP_RTA_DATA(egress), IP_RTA_PAYLOAD(egress));
|
|
|
|
if (ingress->rta_len != IP_RTA_LENGTH(0))
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_VLAN_INGRESS_QOS, IP_RTA_DATA(ingress),
|
|
IP_RTA_PAYLOAD(ingress));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* IPLINK - TUNNEL
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC void
|
|
ipnet_ip_link_info_tunnel_help(Ipnet_ip_config_t *cfg)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " vlan [id <vlan_id>] [egress-qos-map <from:to>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " id <vlan_id> - VLAN ID for this interface"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " egress-qos-map <from:to> - To is VLAN priority <0-7>. From is traffic class number"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ingress-qos-map <from:to> - From is VLAN priority<0-7>. To is traffic class number"IP_LF);
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipnet_ip_link_info_tunnel_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg, struct Ip_rtattr *link_info, const char *dev)
|
|
{
|
|
(void) cfg;
|
|
(void) nlmsg;
|
|
char buf[128];
|
|
|
|
if (IP_NULL != dev)
|
|
ipnet_ip_stdio_printf(cfg, "%s:", dev);
|
|
|
|
if (IP_NULL != link_info)
|
|
{
|
|
struct Ip_rtattr *vattr[IP_IFLA_TUNNEL_MAX + 1];
|
|
struct Ip_rtattr *attr = IP_RTA_DATA(link_info);
|
|
Ip_size_t attrlen = IP_RTA_PAYLOAD(link_info);
|
|
Ip_u32 ival, oval;
|
|
|
|
ipnet_ip_parse_attr(vattr, IP_IFLA_TUNNEL_MAX, attr, attrlen);
|
|
|
|
ipnet_ip_stdio_printf(cfg, " mode %s", ipnet_ip_key_to_str(ipnet_ip_link_tunnel_type, (int)ipnet_ip_rta_u32(vattr[IP_IFLA_VLAN_ID]), buf, sizeof(buf)));
|
|
if (vattr[IP_IFLA_TUNNEL_IKEY] || vattr[IP_IFLA_TUNNEL_OKEY])
|
|
{
|
|
if (IP_NULL == vattr[IP_IFLA_TUNNEL_IKEY])
|
|
ipnet_ip_stdio_printf(cfg, " okey %u", ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_OKEY]));
|
|
else if (IP_NULL == vattr[IP_IFLA_TUNNEL_IKEY])
|
|
ipnet_ip_stdio_printf(cfg, " ikey %u", ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_IKEY]));
|
|
else
|
|
{
|
|
ival = ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_IKEY]);
|
|
oval = ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_OKEY]);
|
|
if (ival == oval)
|
|
ipnet_ip_stdio_printf(cfg, " key %u", ival);
|
|
else
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " okey %u", oval);
|
|
ipnet_ip_stdio_printf(cfg, " ikey %u", ival);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (vattr[IP_IFLA_TUNNEL_ICSUM] && vattr[IP_IFLA_TUNNEL_OCSUM])
|
|
{
|
|
ival = ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_ICSUM]);
|
|
oval = ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_OCSUM]);
|
|
|
|
if (ival == oval)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " %scsum", ival == 0? "-" : "");
|
|
}
|
|
else
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " %sicsum", ival == 0? "-" : "");
|
|
ipnet_ip_stdio_printf(cfg, " %socsum", oval == 0? "-" : "");
|
|
}
|
|
}
|
|
|
|
if (vattr[IP_IFLA_TUNNEL_ISEQ] && vattr[IP_IFLA_TUNNEL_OSEQ])
|
|
{
|
|
ival = ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_ISEQ]);
|
|
oval = ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_OSEQ]);
|
|
|
|
if (ival == oval)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " %sseq", ival == 0? "-" : "");
|
|
}
|
|
else
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " %siseq", ival == 0? "-" : "");
|
|
ipnet_ip_stdio_printf(cfg, " %soseq", oval == 0? "-" : "");
|
|
}
|
|
}
|
|
|
|
if (vattr[IP_IFLA_TUNNEL_TTL])
|
|
ipnet_ip_stdio_printf(cfg, " ttl %u", ipnet_ip_rta_u32(vattr[IP_IFLA_TUNNEL_TTL]));
|
|
}
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_ip_link_info_tunnel_parse(Ipnet_ip_config_t *cfg, struct Ip_rtattr *link_data, Ip_size_t link_data_size, char **ifla_dev)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
Ip_u32 uarg;
|
|
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
/* 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_link_tunnel_attributes, sarg))
|
|
{
|
|
if (IP_NULL != ifla_dev && IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_TUNNEL_ATTRIBUTE_DEVNAME)))
|
|
{
|
|
(void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_TUNNEL_ATTRIBUTE_DEVNAME);
|
|
*ifla_dev = sarg;
|
|
continue;
|
|
}
|
|
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
}
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_DEVNAME:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dev <devname>", arg))
|
|
return -1;
|
|
|
|
if (IP_NULL == ifla_dev)
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dev <devname>");
|
|
|
|
*ifla_dev = sarg;
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_MODE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "mode <ipip|ipv6ipv6|sit|gre|gre6|6to4>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_link_tunnel_type))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "mode <ipip|ipv6ipv6|sit|gre|gre6|6to4>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_MODE, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_LOCAL:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "local <addr>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(IP_AF_UNSPEC, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "local <addr>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_LOCAL, &addr.prefix, addr.prefix_max/8);
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_REMOTE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "remote <addr>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(IP_AF_UNSPEC, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "remote <addr>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_REMOTE, &addr.prefix, addr.prefix_max/8);
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_KEY:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "key <key>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "key <key>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_IKEY, &uarg, sizeof(uarg));
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OKEY, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_IKEY:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "ikey <key>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "ikey <key>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_IKEY, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_OKEY:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "okey <key>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "okey <key>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OKEY, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_ISEQ:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "iseq", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ISEQ, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_NISEQ:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "-iseq", arg))
|
|
return -1;
|
|
|
|
uarg = 0;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ISEQ, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_OSEQ:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "oseq", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OSEQ, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_NOSEQ:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "-oseq", arg))
|
|
return -1;
|
|
|
|
uarg = 0;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OSEQ, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_SEQ:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "seq", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ISEQ, &uarg, sizeof(uarg));
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OSEQ, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_NSEQ:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "-seq", arg))
|
|
return -1;
|
|
|
|
uarg = 0;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ISEQ, &uarg, sizeof(uarg));
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OSEQ, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_ICSUM:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "icsum", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ICSUM, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_NICSUM:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "-icsum", arg))
|
|
return -1;
|
|
|
|
uarg = 0;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ICSUM, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_OCSUM:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "ocsum", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OCSUM, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_NOCSUM:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "-ocsum", arg))
|
|
return -1;
|
|
|
|
uarg = 0;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OCSUM, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_CSUM:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "csum", arg))
|
|
return -1;
|
|
|
|
uarg = 1;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ICSUM, &uarg, sizeof(uarg));
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OCSUM, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_NCSUM:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "-csum", arg))
|
|
return -1;
|
|
|
|
uarg = 0;
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_ICSUM, &uarg, sizeof(uarg));
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_OCSUM, &uarg, sizeof(uarg));
|
|
break;
|
|
case IPNET_IP_TUNNEL_ATTRIBUTE_TTL:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "ttl <ttl>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "ttl <ttl>");
|
|
|
|
ipcom_netlink_rta_addattr_l(link_data, link_data_size, IP_IFLA_TUNNEL_TTL, &uarg, sizeof(uarg));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* IPLINK
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_link_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
int i;
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip link - Display and modify the IPNET link 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 link list [dev <devname>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip link flush"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip link <add|set|delete> [dev <devname>] [name <devname>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " [up] [down] [multicast <on|off>] [allmulticast <on|off>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " [promisc <on|off>] [mtu <mtu>] [link <devname>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " [vr <vr>] [type <typename> [type-specific-parameters]]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip link help"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip link 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 List all links"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " flush Delete all deletable links"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " add Add a link"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " set Manipulate paramters on an existing link"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " delete Remove a link"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " Selector Decription:"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " dev <devname> - The name of the device we are working on"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " name <devname> - Optional name, for example if we are changing a device name"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " link <devname> - Device we want to link to"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " up - Bring the interface UP"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " down - Bring the interface DOWN"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " multicast <on|off> - Turn multicast on or off"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " allmulticast <on|off> - Turn allmulticast on or off"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " promisc <on|off> - Turn promiscous on or off"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " mtu <mtu> - Set the interface MTU"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " vr <vr> - The Virtual Router Identifier"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " type <typename> - The link type name. Must be last on the command line. Everything"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " after this parameter is considered type-specific-parameters"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " Registered typenames and type-specific-parameters:"IP_LF);
|
|
|
|
for (i = 0; IP_NULL != ipnet_ip_link_info_map[i].kind; i++)
|
|
{
|
|
if (ipnet_ip_link_info_map[i].help_linkinfo)
|
|
(*ipnet_ip_link_info_map[i].help_linkinfo) (cfg);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ipnet_ip_link_info_map *
|
|
ipnet_cmd_ip_module_link_info_get(const char *kind)
|
|
{
|
|
int i;
|
|
for (i = 0; IP_NULL != ipnet_ip_link_info_map[i].kind; i++)
|
|
if (ipcom_strcmp(kind, ipnet_ip_link_info_map[i].kind) == 0)
|
|
return &ipnet_ip_link_info_map[i];
|
|
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipnet_cmd_ip_module_link_filter(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_link_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_ifinfomsg *ifm = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
nnlmsg = IPCOM_LIST_NEXT(&nlmsg->next);
|
|
|
|
if (0 != ipnet_ip_parse_reply(nlmsg, IP_IFLA_MAX, sizeof(struct Ip_ifinfomsg)))
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
continue;
|
|
}
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_VR] && (cfg->vr != IPCOM_VR_ANY && cfg->vr != ipnet_ip_rta_s32(nlmsg->rta[IP_IFLA_VR])))
|
|
{
|
|
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_LINK_ATTRIBUTE_DEVNAME:
|
|
if (filter->ifindex != (Ip_u32) ifm->ifi_index)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
case IPNET_IP_LINK_ATTRIBUTE_TYPE:
|
|
if (IP_NULL == nlmsg->rta[IP_IFLA_LINKINFO])
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
else
|
|
{
|
|
struct Ip_rtattr *lattr[IP_IFLA_INFO_MAX + 1];
|
|
struct Ip_rtattr *attr = IP_RTA_DATA(nlmsg->rta[IP_IFLA_LINKINFO]);
|
|
Ip_size_t attrlen = IP_RTA_PAYLOAD(nlmsg->rta[IP_IFLA_LINKINFO]);
|
|
|
|
ipnet_ip_parse_attr(lattr, IP_IFLA_INFO_MAX, attr, attrlen);
|
|
|
|
if (IP_NULL == lattr[IP_IFLA_INFO_KIND])
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
if (ipcom_strcmp(ipnet_ip_rta_str(lattr[IP_IFLA_INFO_KIND]), filter->type) != 0)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
next_message:
|
|
IP_NOOP;
|
|
}
|
|
}
|
|
|
|
IP_STATIC IP_CONST char *
|
|
ipnet_cmd_ip_module_link_print_flags(Ip_u32 flags, char *str, Ip_size_t len)
|
|
{
|
|
Ip_size_t sz = 0;
|
|
unsigned i;
|
|
|
|
str[0] = '\0';
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
if (IP_BIT_ISSET(flags, IP_BIT_UVAL(i)))
|
|
{
|
|
switch (IP_BIT_UVAL(i))
|
|
{
|
|
case IP_IFF_UP:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "UP");
|
|
break;
|
|
case IP_IFF_RUNNING:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "RUNNING");
|
|
break;
|
|
case IP_IFF_LOOPBACK:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "LOOPBACK");
|
|
break;
|
|
case IP_IFF_SIMPLEX:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "SIMPLEX");
|
|
break;
|
|
case IP_IFF_POINTOPOINT:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "POINTOPOINT");
|
|
break;
|
|
case IP_IFF_BROADCAST:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "BROADCAST");
|
|
break;
|
|
case IP_IFF_X_DHCPRUNNING:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "DHCP");
|
|
break;
|
|
case IP_IFF_NOARP:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "NOARP");
|
|
break;
|
|
case IP_IFF_PROMISC:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "PROMISC");
|
|
break;
|
|
case IP_IFF_ALLMULTI:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "ALLMULTI");
|
|
break;
|
|
case IP_IFF_LINK0:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "LINK0");
|
|
break;
|
|
case IP_IFF_LINK1:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "LINK1");
|
|
break;
|
|
case IP_IFF_LINK2:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "LINK2");
|
|
break;
|
|
case IP_IFF_DEBUG:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "DEBUG");
|
|
break;
|
|
case IP_IFF_MASTER:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "MASTER");
|
|
break;
|
|
case IP_IFF_SLAVE:
|
|
sz += (Ip_size_t)ipcom_snprintf(&str[sz], len - sz, "%s%s", sz? "," : "", "SLAVE");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_link_print_internal(Ipnet_ip_config_t *cfg, int family, int print_link, Ipnet_ip_handle_msg_t *nlmsg, const char *link_type)
|
|
{
|
|
char buf[512];
|
|
struct Ip_ifinfomsg *ifm = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
if (cfg->is_silent)
|
|
return 0;
|
|
|
|
(void)ipnet_ip_parse_reply(nlmsg, IP_IFLA_MAX, sizeof(struct Ip_ifinfomsg));
|
|
|
|
if (IP_NULL != link_type)
|
|
{
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_LINKINFO])
|
|
{
|
|
struct Ip_rtattr *lattr[IP_IFLA_INFO_MAX + 1];
|
|
struct Ip_rtattr *attr = IP_RTA_DATA(nlmsg->rta[IP_IFLA_LINKINFO]);
|
|
Ip_size_t attrlen = IP_RTA_PAYLOAD(nlmsg->rta[IP_IFLA_LINKINFO]);
|
|
|
|
ipnet_ip_parse_attr(lattr, IP_IFLA_INFO_MAX, attr, attrlen);
|
|
|
|
if (IP_NULL != lattr[IP_IFLA_INFO_KIND])
|
|
{
|
|
Ipnet_ip_link_info_map *linfo = ipnet_cmd_ip_module_link_info_get(link_type);
|
|
|
|
if (IP_NULL != linfo && IP_NULL != linfo->print_linkinfo)
|
|
{
|
|
(*linfo->print_linkinfo) (cfg, nlmsg, lattr[IP_IFLA_INFO_DATA], nlmsg->rta[IP_IFLA_IFNAME]? ipnet_ip_rta_str(nlmsg->rta[IP_IFLA_IFNAME]) : "<nil>");
|
|
ipnet_ip_stdio_printf(cfg, IP_LF);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (nlmsg->hdr->nlmsg_type == IP_RTM_DELLINK)
|
|
ipnet_ip_stdio_printf(cfg, "Deleted ");
|
|
|
|
/* Index & Name */
|
|
ipnet_ip_stdio_printf(cfg, "%d: %s", ifm->ifi_index, nlmsg->rta[IP_IFLA_IFNAME]? ipnet_ip_rta_str(nlmsg->rta[IP_IFLA_IFNAME]) : "<nil>");
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_LINK])
|
|
{
|
|
Ip_u32 link = ipnet_ip_rta_u32(nlmsg->rta[IP_IFLA_LINK]);
|
|
ipnet_ip_stdio_printf(cfg, "@%s:", link == 0? "NONE" : ipnet_ip_if_indextoname(buf, link, ipnet_ip_rta_vr(cfg, nlmsg->rta[IP_IFLA_VR])));
|
|
}
|
|
else
|
|
ipnet_ip_stdio_printf(cfg, ":");
|
|
|
|
ipnet_ip_stdio_printf(cfg, "<%s>", ipnet_cmd_ip_module_link_print_flags(ifm->ifi_flags, buf, sizeof(buf)));
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_MTU])
|
|
ipnet_ip_stdio_printf(cfg, " mtu %d", ipnet_ip_rta_u32(nlmsg->rta[IP_IFLA_MTU]));
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_QDISC])
|
|
ipnet_ip_stdio_printf(cfg, " qdisc %s", ipnet_ip_rta_str(nlmsg->rta[IP_IFLA_QDISC]));
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_MASTER])
|
|
ipnet_ip_stdio_printf(cfg, " master %s", ipnet_ip_if_indextoname(buf, ipnet_ip_rta_u32(nlmsg->rta[IP_IFLA_MASTER]), ipnet_ip_rta_vr(cfg, nlmsg->rta[IP_IFLA_VR])));
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_TXQLEN])
|
|
ipnet_ip_stdio_printf(cfg, " qlen %d", ipnet_ip_rta_u32(nlmsg->rta[IP_IFLA_TXQLEN]));
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_VR] && cfg->vr != ipnet_ip_rta_s32(nlmsg->rta[IP_IFLA_VR]))
|
|
ipnet_ip_stdio_printf(cfg, " vr %u", ipnet_ip_rta_u32(nlmsg->rta[IP_IFLA_VR]));
|
|
|
|
/* Dump link information */
|
|
if (IP_AF_UNSPEC == family || IP_AF_PACKET == family)
|
|
{
|
|
int i;
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " link/%s", ipnet_ip_key_to_str(ipnet_ip_link_type, ifm->ifi_type, buf, sizeof(buf)));
|
|
|
|
for (i = 0; ipnet_ip_link_type_map[i].family != -1; i++)
|
|
if (ipnet_ip_link_type_map[i].type == ifm->ifi_type)
|
|
break;
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_ADDRESS])
|
|
ipnet_ip_stdio_printf(cfg, " %s", ipnet_ip_format_address(ipnet_ip_link_type_map[i].family,
|
|
IP_RTA_DATA(nlmsg->rta[IP_IFLA_ADDRESS]),
|
|
IP_RTA_PAYLOAD(nlmsg->rta[IP_IFLA_ADDRESS]),
|
|
buf,
|
|
sizeof(buf)));
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_BROADCAST])
|
|
ipnet_ip_stdio_printf(cfg, " %s %s",
|
|
IP_BIT_ISSET(ifm->ifi_flags, IP_IFF_POINTOPOINT)? "peer" : "brd",
|
|
ipnet_ip_format_address(ipnet_ip_link_type_map[i].family,
|
|
IP_RTA_DATA(nlmsg->rta[IP_IFLA_BROADCAST]),
|
|
IP_RTA_PAYLOAD(nlmsg->rta[IP_IFLA_BROADCAST]),
|
|
buf,
|
|
sizeof(buf)));
|
|
}
|
|
|
|
if (print_link)
|
|
{
|
|
if (0 != cfg->show_details && IP_NULL != nlmsg->rta[IP_IFLA_LINKINFO])
|
|
{
|
|
struct Ip_rtattr *lattr[IP_IFLA_INFO_MAX + 1];
|
|
struct Ip_rtattr *attr = IP_RTA_DATA(nlmsg->rta[IP_IFLA_LINKINFO]);
|
|
Ip_size_t attrlen = IP_RTA_PAYLOAD(nlmsg->rta[IP_IFLA_LINKINFO]);
|
|
|
|
ipnet_ip_parse_attr(lattr, IP_IFLA_INFO_MAX, attr, attrlen);
|
|
|
|
if (IP_NULL != lattr[IP_IFLA_INFO_KIND])
|
|
{
|
|
Ipnet_ip_link_info_map *linfo = ipnet_cmd_ip_module_link_info_get(ipnet_ip_rta_str(lattr[IP_IFLA_INFO_KIND]));
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " %s", ipnet_ip_rta_str(lattr[IP_IFLA_INFO_KIND]));
|
|
|
|
if (IP_NULL != linfo && IP_NULL != linfo->print_linkinfo)
|
|
(*linfo->print_linkinfo) (cfg, nlmsg, lattr[IP_IFLA_INFO_DATA], IP_NULL);
|
|
}
|
|
}
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_IFALIAS])
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " alias %s", ipnet_ip_rta_str(nlmsg->rta[IP_IFLA_IFALIAS]));
|
|
}
|
|
|
|
if (0 != cfg->show_stats && (IP_NULL != nlmsg->rta[IP_IFLA_STATS] || IP_NULL != nlmsg->rta[IP_IFLA_STATS64]))
|
|
{
|
|
struct Ip_rtnl_link_stats stats;
|
|
struct Ip_rtnl_link_stats64 stats64;
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, " RX: %-10s %-8s %-8s %-8s %-8s %-8s",
|
|
"bytes", "packets", "errors", "dropped", "overrun", "mcast");
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_STATS64])
|
|
{
|
|
ipcom_memcpy(&stats64, IP_RTA_DATA(nlmsg->rta[IP_IFLA_STATS64]), sizeof(stats64));
|
|
ipnet_ip_stdio_printf(cfg, " %-10llu %-8llu %-8llu %-8llu %-8llu %-8llu",
|
|
(unsigned long long)stats64.rx_bytes, (unsigned long long)stats64.rx_packets, (unsigned long long)stats64.rx_errors, (unsigned long long)stats64.rx_dropped, (unsigned long long)stats64.rx_over_errors, (unsigned long long)stats64.multicast);
|
|
}
|
|
else
|
|
{
|
|
/* Fix alignment -- why do they use structures here, really? */
|
|
ipcom_memcpy(&stats, IP_RTA_DATA(nlmsg->rta[IP_IFLA_STATS]), sizeof(stats));
|
|
ipnet_ip_stdio_printf(cfg, " %-10u %-8u %-8u %-8u %-8u %-8u",
|
|
stats.rx_bytes, stats.rx_packets, stats.rx_errors, stats.rx_dropped, stats.rx_over_errors, stats.multicast);
|
|
}
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
|
|
ipnet_ip_stdio_printf(cfg, " TX: %-10s %-8s %-8s %-8s %-8s %-8s",
|
|
"bytes", "packets", "errors", "dropped", "carrier", "collsns");
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
if (IP_NULL != nlmsg->rta[IP_IFLA_STATS64])
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " %-10llu %-8llu %-8llu %-8llu %-8llu %-8llu",
|
|
(unsigned long long)stats64.tx_bytes, (unsigned long long)stats64.tx_packets, (unsigned long long)stats64.tx_errors, (unsigned long long)stats64.tx_dropped, (unsigned long long)stats64.tx_carrier_errors, (unsigned long long)stats64.collisions);
|
|
}
|
|
else
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " %-10u %-8u %-8u %-8u %-8u %-8u",
|
|
stats.tx_bytes, stats.tx_packets, stats.tx_errors, stats.tx_dropped, stats.tx_carrier_errors, stats.collisions);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ipnet_ip_stdio_printf(cfg, IP_LF);
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_GLOBAL int
|
|
ipnet_cmd_ip_module_link_print(Ipnet_ip_config_t *cfg, int family, int print_link, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
return ipnet_cmd_ip_module_link_print_internal(cfg, family, print_link, nlmsg, IP_NULL);
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_list_parse(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_link_filter_t *filter, const char *link_type)
|
|
{
|
|
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_link_attributes, sarg))
|
|
{
|
|
if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_LINK_ATTRIBUTE_DEVNAME)))
|
|
{
|
|
(void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_LINK_ATTRIBUTE_DEVNAME);
|
|
filter->ifindex = ipnet_ip_if_nametoindex(sarg, cfg->vr);
|
|
if (0 == filter->ifindex)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to resolve interface name \'%s\'"IP_LF, sarg);
|
|
return -1;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
}
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_LINK_ATTRIBUTE_TYPE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "type <name>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "type <name>");
|
|
|
|
ipcom_strncpy(filter->type, sarg, sizeof(filter->type));
|
|
filter->type[sizeof(filter->type)-1] = '\0';
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_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 (0 == filter->ifindex)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to resolve interface name \'%s\'"IP_LF, sarg);
|
|
return -1;
|
|
}
|
|
break;
|
|
default:
|
|
return ipnet_cmd_ip_link_usage(cfg, -1);
|
|
}
|
|
}
|
|
|
|
if (IP_NULL != link_type)
|
|
{
|
|
(void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_LINK_ATTRIBUTE_TYPE);
|
|
ipcom_strncpy(filter->type, link_type, sizeof(filter->type));
|
|
filter->type[sizeof(filter->type)-1] = '\0';
|
|
}
|
|
|
|
/* All parameters are parsed
|
|
* Store the argument match mask
|
|
*/
|
|
ipcom_memcpy(&filter->mask, &cfg->mask, sizeof(filter->mask));
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_list(Ipnet_ip_config_t *cfg, const char *link_type)
|
|
{
|
|
Ipnet_cmd_ip_module_link_filter_t filter;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_link_list_parse(cfg, &filter, link_type);
|
|
|
|
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_GETLINK, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump routing table, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Filter the reply chain */
|
|
ipnet_cmd_ip_module_link_filter(cfg, &filter);
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
ipnet_cmd_ip_module_link_print_internal(cfg, IP_AF_UNSPEC, IP_TRUE, nlmsg, link_type);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_flush(Ipnet_ip_config_t *cfg, const char *link_type)
|
|
{
|
|
Ipnet_cmd_ip_module_link_filter_t filter;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_link_list_parse(cfg, &filter, link_type);
|
|
|
|
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_GETLINK, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump routing table, error = %d"IP_LF, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Filter the reply chain */
|
|
ipnet_cmd_ip_module_link_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_NEWLINK)
|
|
continue;
|
|
|
|
nlmsg->hdr->nlmsg_type = IP_RTM_DELLINK;
|
|
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_link_print_internal(cfg, IP_AF_UNSPEC, IP_TRUE, nlmsg, link_type);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_ifla_modify(Ipnet_ip_config_t *cfg, const char *ifla_type, char **ifla_dev)
|
|
{
|
|
struct Ip_rtattr *ifla = (struct Ip_rtattr *)&cfg->handle->rx[0];
|
|
struct Ip_rtattr *ifla_data = (struct Ip_rtattr *)&cfg->handle->rx[IPNET_IP_HANDLE_BUFFER/2];
|
|
Ipnet_ip_link_info_map *linfo = ipnet_cmd_ip_module_link_info_get(ifla_type);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
Ip_u64 mask = cfg->mask;
|
|
|
|
ifla->rta_type = IP_IFLA_LINKINFO;
|
|
ifla->rta_len = IP_RTA_LENGTH(0);
|
|
|
|
ipcom_netlink_rta_addattr_l(ifla, IPNET_IP_HANDLE_BUFFER/2, IP_IFLA_INFO_KIND, ifla_type, ipcom_strlen(ifla_type) + 1);
|
|
|
|
if (IP_NULL != linfo && IP_NULL != linfo->parse_linkinfo)
|
|
{
|
|
Ip_ssize_t ret;
|
|
|
|
ifla_data->rta_type = IP_IFLA_INFO_DATA;
|
|
ifla_data->rta_len = IP_RTA_LENGTH(0);
|
|
if (0 > (ret = (*linfo->parse_linkinfo) (cfg, ifla_data, IPNET_IP_HANDLE_BUFFER/2, ifla_dev)))
|
|
return ret;
|
|
|
|
if (IP_RTA_LENGTH(0) != ifla_data->rta_len)
|
|
ipcom_netlink_rta_addattr_l(ifla, IPNET_IP_HANDLE_BUFFER/2, IP_IFLA_INFO_DATA, IP_RTA_DATA(ifla_data), IP_RTA_PAYLOAD(ifla_data));
|
|
}
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_LINKINFO, IP_RTA_DATA(ifla), IP_RTA_PAYLOAD(ifla));
|
|
ipnet_cmd_ip_set_mask(cfg, mask);
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_modify(Ipnet_ip_config_t *cfg, char **ifla_dev, const char *link_type)
|
|
{
|
|
char *sarg;
|
|
Ip_size_t sz;
|
|
int arg;
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_ifinfomsg *ifm;
|
|
Ip_u32 uarg;
|
|
unsigned char pbuf[64];
|
|
|
|
ipcom_memset(nlh, 0, sizeof(*nlh));
|
|
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
|
|
|
|
/* Start of the routing message */
|
|
ifm = (struct Ip_ifinfomsg *)IP_NLMSG_DATA(nlh);
|
|
ipcom_memset(ifm, 0, sizeof(*ifm));
|
|
ifm->ifi_family = IP_AF_UNSPEC;
|
|
|
|
/* Move past the routing header */
|
|
nlh->nlmsg_len = (Ip_u32) (IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*ifm));
|
|
|
|
/* */
|
|
*ifla_dev = IP_NULL;
|
|
|
|
if (IP_NULL != link_type)
|
|
{
|
|
(void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_LINK_ATTRIBUTE_TYPE);
|
|
return ipnet_cmd_ip_module_link_ifla_modify(cfg, link_type, ifla_dev);
|
|
}
|
|
|
|
/* 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_link_attributes, sarg))
|
|
{
|
|
if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_LINK_ATTRIBUTE_DEVNAME)))
|
|
{
|
|
(void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_LINK_ATTRIBUTE_DEVNAME);
|
|
*ifla_dev = sarg;
|
|
|
|
continue;
|
|
}
|
|
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
}
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_LINK_ATTRIBUTE_HELP:
|
|
return ipnet_cmd_ip_link_usage(cfg, 0);
|
|
case IPNET_IP_LINK_ATTRIBUTE_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>");
|
|
|
|
*ifla_dev = sarg;
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_NAME:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "name <devname>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "name <devname>");
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_IFNAME, sarg, ipcom_strlen(sarg) + 1);
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_LINK:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "link <devname>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "link <devname>");
|
|
|
|
/* RESOLVE SPARAM TO IFINDEX */
|
|
uarg = ipnet_ip_if_nametoindex(sarg, cfg->vr);
|
|
if (0 == arg)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to resolve interface name \'%s\'"IP_LF, sarg);
|
|
return -1;
|
|
}
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_LINK, &uarg, sizeof(Ip_u32));
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_ADDRESS:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "address <address>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "address <address>");
|
|
|
|
sz = ipnet_ip_str_to_link_address(sarg, pbuf);
|
|
if (0 == sz)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to parse \"%s\" to a valid address"IP_LF, sarg);
|
|
return -1;
|
|
}
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_ADDRESS, pbuf, sz);
|
|
break;
|
|
case IPNET_IP_LINK_ATTRIBUTE_BROADCAST:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "broadcast <address>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "broadcast <address>");
|
|
|
|
sz = ipnet_ip_str_to_link_address(sarg, pbuf);
|
|
if (0 == sz)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to parse \"%s\" to a valid address"IP_LF, sarg);
|
|
return -1;
|
|
}
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_BROADCAST, pbuf, sz);
|
|
break;
|
|
case IPNET_IP_LINK_ATTRIBUTE_MTU:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "mtu <mtu>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "mtu <mtu>");
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_MTU, &uarg, sizeof(Ip_u32));
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_VR:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "vr <vr>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "vr <vr>");
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_VR, &uarg, sizeof(Ip_u32));
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_UP:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "up", arg))
|
|
return -1;
|
|
|
|
ifm->ifi_change |= IP_IFF_UP;
|
|
ifm->ifi_flags |= IP_IFF_UP;
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_DOWN:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "down", arg))
|
|
return -1;
|
|
ifm->ifi_change |= (Ip_u32)IP_IFF_UP;
|
|
ifm->ifi_flags &= (Ip_u32)~IP_IFF_UP;
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_MULTICAST:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "multicast <on|off>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_onoff_values))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "multicast <on|off>");
|
|
|
|
ifm->ifi_change |= (Ip_u32)IP_IFF_MULTICAST;
|
|
if (uarg)
|
|
ifm->ifi_flags |= (Ip_u32)IP_IFF_MULTICAST;
|
|
else
|
|
ifm->ifi_flags &= (Ip_u32)~IP_IFF_MULTICAST;
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_ALLMULTI:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "allmulticast <on|off>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_onoff_values))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "allmulticast <on|off>");
|
|
|
|
ifm->ifi_change |= (Ip_u32)IP_IFF_ALLMULTI;
|
|
if (uarg)
|
|
ifm->ifi_flags |= (Ip_u32)IP_IFF_ALLMULTI;
|
|
else
|
|
ifm->ifi_flags &= (Ip_u32)~IP_IFF_ALLMULTI;
|
|
break;
|
|
case IPNET_IP_LINK_ATTRIBUTE_PROMISC:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "promisc <on|off>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_onoff_values))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "promisc <on|off>");
|
|
|
|
ifm->ifi_change |= (Ip_u32)IP_IFF_PROMISC;
|
|
if (uarg)
|
|
ifm->ifi_flags |= (Ip_u32)IP_IFF_PROMISC;
|
|
else
|
|
ifm->ifi_flags &= (Ip_u32)~IP_IFF_PROMISC;
|
|
break;
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_TYPE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "type <typename>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "type <typename>");
|
|
|
|
return ipnet_cmd_ip_module_link_ifla_modify(cfg, sarg, IP_NULL);
|
|
|
|
case IPNET_IP_LINK_ATTRIBUTE_NOOP_ARG:
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, sarg);
|
|
|
|
/* FALL THROUGH */
|
|
case IPNET_IP_LINK_ATTRIBUTE_NOOP:
|
|
/* Dont do anything */
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_add(Ipnet_ip_config_t *cfg, Ip_u16 nlmsg_flags, const char *link_type)
|
|
{
|
|
char *ifla_dev;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_link_modify(cfg, &ifla_dev, link_type);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
|
|
if (0 <= ret)
|
|
{
|
|
nlh->nlmsg_flags = nlmsg_flags|IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_RTM_NEWLINK;
|
|
|
|
if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_LINK_ATTRIBUTE_TYPE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "\'type <typename>\' argument is required"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_LINK_ATTRIBUTE_NAME)))
|
|
{
|
|
if (IP_NULL == ifla_dev)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "\'dev <devname>\' or \'name <devname>\' argument is required"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_IFLA_IFNAME, ifla_dev, ipcom_strlen(ifla_dev) + 1);
|
|
}
|
|
|
|
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_link_set(Ipnet_ip_config_t *cfg, const char *link_type)
|
|
{
|
|
char *ifla_dev;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_link_modify(cfg, &ifla_dev, link_type);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_ifinfomsg *ifm = (struct Ip_ifinfomsg *)IP_NLMSG_DATA(nlh);
|
|
|
|
if (0 <= ret)
|
|
{
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_RTM_SETLINK;
|
|
|
|
if (IP_NULL == ifla_dev)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "\'dev <devname>\' argument is required"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
ifm->ifi_index = (Ip_s32) ipnet_ip_if_nametoindex(ifla_dev, cfg->vr);
|
|
if (0 == ifm->ifi_index)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Cannot find device \"%s\""IP_LF, ifla_dev);
|
|
return -1;
|
|
}
|
|
|
|
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_link_del(Ipnet_ip_config_t *cfg, const char *link_type)
|
|
{
|
|
char *ifla_dev;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_link_modify(cfg, &ifla_dev, link_type);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_ifinfomsg *ifm = (struct Ip_ifinfomsg *)IP_NLMSG_DATA(nlh);
|
|
|
|
if (0 <= ret)
|
|
{
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_RTM_DELLINK;
|
|
|
|
if (IP_NULL == ifla_dev)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "\'dev <devname>\' argument is required"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
ifm->ifi_index = (Ip_s32)ipnet_ip_if_nametoindex(ifla_dev, cfg->vr);
|
|
if (0 == ifm->ifi_index)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Cannot find device \"%s\""IP_LF, ifla_dev);
|
|
return -1;
|
|
}
|
|
|
|
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_link(Ipnet_ip_config_t *cfg, const char *link_type)
|
|
{
|
|
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_link_usage(cfg, -1);
|
|
|
|
/* Resolve the module */
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_link_main, sparam))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
|
|
else
|
|
{
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_LINK_MAIN_HELP:
|
|
return ipnet_cmd_ip_link_usage(cfg, 0);
|
|
case IPNET_IP_LINK_MAIN_LIST:
|
|
return ipnet_cmd_ip_module_link_list(cfg, link_type);
|
|
case IPNET_IP_LINK_MAIN_FLUSH:
|
|
return ipnet_cmd_ip_module_link_flush(cfg, link_type);
|
|
case IPNET_IP_LINK_MAIN_ADD:
|
|
return ipnet_cmd_ip_module_link_add(cfg, IP_NLM_F_CREATE|IP_NLM_F_EXCL, link_type);
|
|
case IPNET_IP_LINK_MAIN_REPLACE:
|
|
return ipnet_cmd_ip_module_link_add(cfg, IP_NLM_F_CREATE|IP_NLM_F_REPLACE, link_type);
|
|
case IPNET_IP_LINK_MAIN_SET:
|
|
return ipnet_cmd_ip_module_link_set(cfg, link_type);
|
|
case IPNET_IP_LINK_MAIN_DEL:
|
|
return ipnet_cmd_ip_module_link_del(cfg, link_type);
|
|
case IPNET_IP_LINK_MAIN_MONITOR:
|
|
return ipnet_cmd_ip_module_monitor(cfg, IP_BIT_VAL(IPNET_IP_MODULE_LINK));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_GLOBAL Ip_u32
|
|
ipnet_cmd_ip_module_link_monitor_groups(Ipnet_ip_config_t *cfg)
|
|
{
|
|
(void) cfg;
|
|
return IP_RTMGRP_LINK;
|
|
}
|
|
|
|
IP_GLOBAL Ip_bool
|
|
ipnet_cmd_ip_module_link_monitor(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
if (nlmsg->hdr->nlmsg_type == IP_RTM_NEWLINK || nlmsg->hdr->nlmsg_type == IP_RTM_DELLINK)
|
|
{
|
|
ipnet_cmd_ip_module_link_print(cfg, IP_AF_UNSPEC, 1, nlmsg);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
IP_GLOBAL Ip_ssize_t
|
|
ipnet_cmd_ip_module_link_flush_all(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_GETLINK, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump routing table, error = %d"IP_LF, (int)ret);
|
|
return ret;
|
|
}
|
|
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
{
|
|
struct Ip_ifinfomsg *ifm = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
if (nlmsg->hdr->nlmsg_type != IP_RTM_NEWLINK)
|
|
continue;
|
|
|
|
/* DOWN */
|
|
nlmsg->hdr->nlmsg_type = IP_RTM_SETLINK;
|
|
nlmsg->hdr->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
ifm->ifi_change = IP_IFF_UP|IP_IFF_RUNNING;
|
|
ifm->ifi_flags = 0;
|
|
(void)ipnet_ip_request_netlink(cfg, cfg->handle, nlmsg->hdr, cfg->core, IP_TRUE);
|
|
|
|
/* DELETE */
|
|
nlmsg->hdr->nlmsg_type = IP_RTM_DELLINK;
|
|
(void)ipnet_ip_request_netlink(cfg, cfg->handle, nlmsg->hdr, cfg->core, IP_TRUE);
|
|
|
|
ipnet_cmd_ip_module_link_print(cfg, IP_AF_UNSPEC, IP_TRUE, nlmsg);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#endif /* IPNET_USE_NETLINK */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|