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