/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ip_vr.c,v $ $Revision: 1.2.40.4 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ip_vr.c,v $ * $Author: hxie $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifdef IPCOM_KERNEL #undef IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #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_VR_HELP, IPNET_IP_VR_LIST, IPNET_IP_VR_ADD, IPNET_IP_VR_DEL, IPNET_IP_VR_CHANGE, IPNET_IP_VR_MONITOR }; enum { IPNET_IP_VR_ATTRIBUTE_VR, IPNET_IP_VR_ATTRIBUTE_NEWVR, IPNET_IP_VR_ATTRIBUTE_DEVNAME, IPNET_IP_VR_ATTRIBUTE_TABLE, IPNET_IP_VR_ATTRIBUTE_HELP }; /* **************************************************************************** * 5 TYPES **************************************************************************** */ typedef struct Ipnet_cmd_ip_module_vr_filter_struct { Ip_u64 mask; Ip_u16 vr; char ifname[IP_IFNAMSIZ+1]; } Ipnet_cmd_ip_module_vr_filter_t; /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ static Ipcom_cmd_int_str_map ipnet_ip_vr_main[] = { { IPNET_IP_VR_HELP, "help" }, { IPNET_IP_VR_LIST, "show" }, { IPNET_IP_VR_LIST, "list" }, { IPNET_IP_VR_LIST, "lst" }, { IPNET_IP_VR_LIST, "get" }, { IPNET_IP_VR_ADD, "add" }, { IPNET_IP_VR_DEL, "delete" }, { IPNET_IP_VR_DEL, "del" }, { IPNET_IP_VR_CHANGE, "change" }, { IPNET_IP_VR_CHANGE, "chg" }, { IPNET_IP_VR_MONITOR, "monitor" }, { -1, IP_NULL }, }; static Ipcom_cmd_int_str_map ipnet_ip_vr_attributes[] = { { IPNET_IP_VR_ATTRIBUTE_VR, "vr" }, { IPNET_IP_VR_ATTRIBUTE_NEWVR, "newvr" }, { IPNET_IP_VR_ATTRIBUTE_DEVNAME, "dev" }, { IPNET_IP_VR_ATTRIBUTE_TABLE, "table" }, { IPNET_IP_VR_ATTRIBUTE_HELP, "help" }, { -1, IP_NULL }, }; /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * IPLINK - VLAN **************************************************************************** */ /* **************************************************************************** * IPVR **************************************************************************** */ IP_STATIC int ipnet_cmd_ip_vr_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 vr - Display and modify the IPNET virtual router 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 vr list [vr ] [dev ]"IP_LF); ipnet_ip_stdio_printf(cfg, " ip vr > [table ]"IP_LF); ipnet_ip_stdio_printf(cfg, " ip vr change > dev >"IP_LF); ipnet_ip_stdio_printf(cfg, " ip vr help"IP_LF); ipnet_ip_stdio_printf(cfg, " ip vr 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, " 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, " vr - The Virtual Router Identifier we are requesting in"IP_LF); ipnet_ip_stdio_printf(cfg, " newvr - The Virtual Router Identifier we want to move the device to"IP_LF); ipnet_ip_stdio_printf(cfg, " dev - The name of the device we are working on"IP_LF); ipnet_ip_stdio_printf(cfg, " table
- Routing Table number"IP_LF); return ret; } IP_STATIC void ipnet_cmd_ip_module_vr_filter(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_vr_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_vrmsg *vrm = IP_NLMSG_DATA(nlmsg->hdr); nnlmsg = IPCOM_LIST_NEXT(&nlmsg->next); if (0 != ipnet_ip_parse_reply(nlmsg, IP_VR_MAX, sizeof(struct Ip_vrmsg))) { 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_VR_ATTRIBUTE_DEVNAME: if (IP_NULL == nlmsg->rta[IP_VR_IFNAME] || ipcom_strcmp(ipnet_ip_rta_str(nlmsg->rta[IP_VR_IFNAME]), filter->ifname)) { ipnet_ip_free_reply(nlmsg); goto next_message; } break; case IPNET_IP_VR_ATTRIBUTE_VR: if (filter->vr != vrm->vr_vr) { ipnet_ip_free_reply(nlmsg); goto next_message; } break; } } } next_message: IP_NOOP; } } IP_STATIC int ipnet_cmd_ip_module_vr_print(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_vr_filter_t *filter, Ipnet_ip_handle_msg_t *nlmsg) { struct Ip_vrmsg *vrm = IP_NLMSG_DATA(nlmsg->hdr); (void) filter; if (cfg->is_silent) return 0; (void)ipnet_ip_parse_reply(nlmsg, IP_VR_MAX, sizeof(struct Ip_vrmsg)); if (nlmsg->hdr->nlmsg_type == IP_RTM_DELVR) ipnet_ip_stdio_printf(cfg, "Deleted "); else if (nlmsg->hdr->nlmsg_type == IP_RTM_CHANGEVR) ipnet_ip_stdio_printf(cfg, "Change "); /* Index & Name */ ipnet_ip_stdio_printf(cfg, "vr %d", vrm->vr_vr); if (IP_NULL != nlmsg->rta[IP_VR_VR]) ipnet_ip_stdio_printf(cfg, " newvr %d", ipnet_ip_rta_u32(nlmsg->rta[IP_VR_VR])); if (IP_NULL != nlmsg->rta[IP_VR_TABLE]) ipnet_ip_stdio_printf(cfg, " table %d", ipnet_ip_rta_u32(nlmsg->rta[IP_VR_TABLE])); if (IP_NULL != nlmsg->rta[IP_VR_IFNAME]) ipnet_ip_stdio_printf(cfg, " dev %s", ipnet_ip_rta_str(nlmsg->rta[IP_VR_IFNAME])); ipnet_ip_stdio_printf(cfg, IP_LF); return 0; } IP_STATIC Ip_ssize_t ipnet_cmd_ip_module_vr_list_parse(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_vr_filter_t *filter) { char *sarg; int arg; Ip_u32 uarg; /* 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_vr_attributes, sarg)) { if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_VR_ATTRIBUTE_VR))) { (void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_VR_ATTRIBUTE_VR); if (IP_TRUE != ipnet_ip_str_to_uint(&uarg, sarg, IP_NULL)) return ipnet_cmd_ip_unknown_keyword(cfg, sarg); filter->vr = (Ip_u16) uarg; continue; } return ipnet_cmd_ip_unknown_keyword(cfg, sarg); } switch (arg) { case IPNET_IP_VR_ATTRIBUTE_VR: if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "vr ", arg)) return -1; if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL)) return ipnet_cmd_ip_requires_argument(cfg, "vr "); filter->vr = (Ip_u16) uarg; break; case IPNET_IP_VR_ATTRIBUTE_DEVNAME: if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dev ", arg)) return -1; if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg)) return ipnet_cmd_ip_requires_argument(cfg, "dev "); if (ipcom_strlen(sarg) >= sizeof(filter->ifname)) return -1; ipcom_strncpy(filter->ifname, sarg, sizeof(filter->ifname)); filter->ifname[sizeof(filter->ifname)-1] = '\0'; break; default: return ipnet_cmd_ip_unknown_keyword(cfg, sarg); } } /* 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_vr_list(Ipnet_ip_config_t *cfg) { Ipnet_cmd_ip_module_vr_filter_t filter; Ip_ssize_t ret = ipnet_cmd_ip_module_vr_list_parse(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_GETVR, cfg->family, cfg->core, IP_TRUE))) { ipnet_ip_stdio_printf(cfg, "Unable to dump virtual routers, error = %d"IP_LF, (int)ret); return ret; } /* Filter the reply chain */ ipnet_cmd_ip_module_vr_filter(cfg, &filter); for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next)) ipnet_cmd_ip_module_vr_print(cfg, &filter, nlmsg); } return ret; } IP_STATIC Ip_ssize_t ipnet_cmd_ip_module_vr_modify(Ipnet_ip_config_t *cfg) { char *sarg; int arg; struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0]; struct Ip_vrmsg *vrm; Ip_u32 uarg; ipcom_memset(nlh, 0, sizeof(*nlh)); nlh->nlmsg_len = IP_NLMSG_LENGTH(0); /* Start of the routing message */ vrm = (struct Ip_vrmsg *)IP_NLMSG_DATA(nlh); ipcom_memset(vrm, 0, sizeof(*vrm)); vrm->vr_family = IP_AF_PACKET; vrm->vr_vr = IPCOM_VR_ANY; /* Move past the routing header */ nlh->nlmsg_len = (Ip_u32) (IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*vrm)); /* 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_vr_attributes, sarg)) { if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_VR_ATTRIBUTE_VR))) { (void)ipnet_cmd_ip_check_mask(cfg, IP_NULL, IPNET_IP_VR_ATTRIBUTE_VR); if (IP_TRUE != ipnet_ip_str_to_uint(&uarg, sarg, IP_NULL)) return ipnet_cmd_ip_unknown_keyword(cfg, sarg); vrm->vr_vr = (Ip_u16) uarg; continue; } return ipnet_cmd_ip_unknown_keyword(cfg, sarg); } switch (arg) { case IPNET_IP_VR_ATTRIBUTE_HELP: return ipnet_cmd_ip_vr_usage(cfg, 0); case IPNET_IP_VR_ATTRIBUTE_DEVNAME: if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dev ", arg)) return -1; if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg)) return ipnet_cmd_ip_requires_argument(cfg, "dev "); ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_VR_IFNAME, sarg, ipcom_strlen(sarg) + 1); break; case IPNET_IP_VR_ATTRIBUTE_VR: if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "vr ", arg)) return -1; if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL)) return ipnet_cmd_ip_requires_argument(cfg, "vr "); vrm->vr_vr = (Ip_u16) uarg; break; case IPNET_IP_VR_ATTRIBUTE_NEWVR: if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "newvr ", arg)) return -1; if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL)) return ipnet_cmd_ip_requires_argument(cfg, "newvr "); ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_VR_VR, &uarg, sizeof(uarg)); break; case IPNET_IP_VR_ATTRIBUTE_TABLE: if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "table
", arg)) return -1; if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL)) return ipnet_cmd_ip_requires_argument(cfg, "table
"); ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_VR_TABLE, &uarg, sizeof(uarg)); break; } } return 0; } IP_STATIC Ip_ssize_t ipnet_cmd_ip_module_vr_add(Ipnet_ip_config_t *cfg) { Ip_ssize_t ret = ipnet_cmd_ip_module_vr_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_NEWVR; if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_VR_ATTRIBUTE_VR))) { ipnet_ip_stdio_printf(cfg, "\'vr \' argument is required"IP_LF); 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_vr_change(Ipnet_ip_config_t *cfg) { Ip_ssize_t ret = ipnet_cmd_ip_module_vr_modify(cfg); struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0]; if (0 <= ret) { nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK; nlh->nlmsg_type = IP_RTM_CHANGEVR; if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_VR_ATTRIBUTE_NEWVR))) { ipnet_ip_stdio_printf(cfg, "\'newvr \' argument is required"IP_LF); return -1; } if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_VR_ATTRIBUTE_DEVNAME))) { ipnet_ip_stdio_printf(cfg, "\'dev \' argument is required"IP_LF); 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_vr_del(Ipnet_ip_config_t *cfg) { Ip_ssize_t ret = ipnet_cmd_ip_module_vr_modify(cfg); struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0]; if (0 <= ret) { nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK; nlh->nlmsg_type = IP_RTM_DELVR; if (IP_BIT_ISFALSE(cfg->mask, IP_BIT_UVAL64(IPNET_IP_VR_ATTRIBUTE_VR))) { ipnet_ip_stdio_printf(cfg, "\'vr \' argument is required"IP_LF); 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_vr(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_vr_usage(cfg, -1); /* Resolve the module */ if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_vr_main, sparam)) return ipnet_cmd_ip_unknown_keyword(cfg, sparam); else { ipnet_cmd_ip_clear_mask(cfg); switch (arg) { case IPNET_IP_VR_HELP: return ipnet_cmd_ip_vr_usage(cfg, 0); case IPNET_IP_VR_LIST: return ipnet_cmd_ip_module_vr_list(cfg); case IPNET_IP_VR_ADD: return ipnet_cmd_ip_module_vr_add(cfg); case IPNET_IP_VR_CHANGE: return ipnet_cmd_ip_module_vr_change(cfg); case IPNET_IP_VR_DEL: return ipnet_cmd_ip_module_vr_del(cfg); case IPNET_IP_VR_MONITOR: return ipnet_cmd_ip_module_monitor(cfg, IP_BIT_VAL(IPNET_IP_MODULE_VR)); } } return 0; } IP_GLOBAL Ip_u32 ipnet_cmd_ip_module_vr_monitor_groups(Ipnet_ip_config_t *cfg) { (void) cfg; return IP_RTMGRP_RTAB; } IP_GLOBAL Ip_bool ipnet_cmd_ip_module_vr_monitor(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg) { if (nlmsg->hdr->nlmsg_type == IP_RTM_NEWVR || nlmsg->hdr->nlmsg_type == IP_RTM_DELVR || nlmsg->hdr->nlmsg_type == IP_RTM_CHANGEVR) { ipnet_cmd_ip_module_vr_print(cfg, IP_NULL, nlmsg); return IP_TRUE; } return IP_FALSE; } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ #endif /* IPNET_USE_NETLINK */ /* **************************************************************************** * END OF FILE **************************************************************************** */