/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipnet_cmd_arp.c,v $ $Revision: 1.50.10.4 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_arp.c,v $ * $Author: lwang7 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifdef IPCOM_KERNEL #undef IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #ifdef IPCOM_USE_INET #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include "ipnet.h" #include "ipnet_eth.h" #include "ipnet_cmd.h" #include "ipnet_routesock.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_arp_print_entry *=========================================================================== * Description: Prints an ARP entry. * Parameters: rt - An ARP entry. * addrs - Addresses in the ARP entry. * Returns: 0 == success, <0 == error * */ IP_STATIC int ipnet_arp_print_entry(struct Ipnet_rt_msghdr *rt, struct Ip_sockaddr *addrs[IPNET_RTAX_MAX]) { char str_addr[IPNET_ETH_ADDR_SIZE * 3]; char ifname[IP_IFNAMSIZ]; (void)ipcom_inet_ntop(IP_AF_INET, &((struct Ip_sockaddr_in*) addrs[IPNET_RTAX_DST])->sin_addr, str_addr, sizeof(str_addr)); ipcom_printf("%16s", str_addr); ipcom_printf(" at %s ", ipcom_cmd_sockaddr_to_str(addrs[IPNET_RTAX_GATEWAY], IP_FALSE, IP_TRUE, str_addr, sizeof(str_addr))); if (IP_BIT_ISSET(rt->rtm_flags, IPNET_RTF_LOCAL)) ipcom_printf("local "); if (rt->rtm_rmx.rmx_expire == IPCOM_ADDR_INFINITE) ipcom_printf("permanent "); if (IP_BIT_ISSET(rt->rtm_flags, IPNET_RTF_PROTO2)) ipcom_printf("published "); ipcom_printf("on %s"IP_LF, ipcom_if_indextoname(rt->rtm_index, ifname)); return 0; } /* *=========================================================================== * ipnet_arp_delete_or_probe *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipnet_arp_delete_or_probe(Ip_bool silent, Ip_u32 ifindex, IP_CONST char *str_ip4_addr, Ip_bool is_delete) { struct Ip_arpreq arpreq; struct Ip_sockaddr_in *addr = (struct Ip_sockaddr_in *) &arpreq.arp_pa; int ret; ipcom_memset(&arpreq, 0, sizeof(arpreq)); IPCOM_SA_LEN_SET(&arpreq.arp_ha, sizeof(arpreq.arp_ha)); arpreq.arp_ha.sdl_family = IP_AF_LINK; arpreq.arp_ha.sdl_type = IP_IFT_ETHER; arpreq.arp_ha.sdl_index = (Ip_u16) ifindex; IPCOM_SA_LEN_SET(&arpreq.arp_pa, sizeof(struct Ip_sockaddr)); arpreq.arp_pa.sa_family = IP_AF_INET; ret = ipcom_inet_pton(IP_AF_INET, str_ip4_addr, &addr->sin_addr); if (ret == -1) goto errout; if (ret == 0) { if (silent == IP_FALSE) ipcom_printf("arp: %s is not a valid IPv4 address."IP_LF, str_ip4_addr); } else { int s; s = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0); if (s < 0) goto errout; ret = ipcom_socketioctl(s, is_delete ? IP_SIOCDARP : IP_SIOCPARP, &arpreq); ipcom_socketclose(s); if (ret < 0) goto errout; if (is_delete && silent == IP_FALSE) ipcom_printf("arp: %s deleted."IP_LF, str_ip4_addr); } return 0; errout: return -ipcom_errno; } /* *=========================================================================== * ipnet_arp_delete_entry *=========================================================================== * Description: Deletes a single ARP entry * Parameters: silent - IP_TRUE to quince if all output to stdout. * ifindex - interface the ARP entry is assigned to * str_ip4_addr - the IPv4 address of the ARP entry * Returns: 0 = success * <0 = negative errno * */ IP_STATIC int ipnet_arp_delete_entry(Ip_bool silent, Ip_u32 ifindex, IP_CONST char *str_ip4_addr) { return ipnet_arp_delete_or_probe(silent, ifindex, str_ip4_addr, IP_TRUE); } /* *=========================================================================== * ipnet_arp_delete_cb *=========================================================================== * Description: Deletes a single ARP entry. * Parameters: rt - An ARP entry. * addrs - Addresses in the ARP entry. * Returns: 0 == success, <0 == error * */ IP_STATIC int ipnet_arp_delete_cb(struct Ipnet_rt_msghdr *rt, struct Ip_sockaddr *addrs[IPNET_RTAX_MAX]) { char addr_str[IP_INET_ADDRSTRLEN]; struct Ip_sockaddr_in *in; in = (struct Ip_sockaddr_in *) addrs[IPNET_RTAX_DST]; return ipnet_arp_delete_entry(IP_TRUE, rt->rtm_index, ipcom_inet_ntop(IP_AF_INET, &in->sin_addr, addr_str, sizeof(addr_str))); } /* *=========================================================================== * ipnet_arp_force_probe *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipnet_arp_force_probe(Ip_bool silent, Ip_u32 ifindex, IP_CONST char *str_ip4_addr) { return ipnet_arp_delete_or_probe(silent, ifindex, str_ip4_addr, IP_FALSE); } /* *=========================================================================== * ipnet_arp_add_entry *=========================================================================== * Description: Adds an ARP entry. * Parameters: silent - IP_TRUE to quench all output to stdout. * str_ip4_addr - IPv4 address * str_link_addr - Ethernet address * ifindex - interface index the entry should be added to * arp_flags - IP_ATF_xxx flags. * is_add - IP_TRUE if this is really an add request * IP_FALSE if an unsolicitated ARP response should * be sent * Returns: 0 = success * <0 = negative errno * */ IP_STATIC int ipnet_arp_add_entry(Ip_bool silent, IP_CONST char *str_ip4_addr, IP_CONST char *str_link_addr, Ip_u32 ifindex, int arp_flags, Ip_bool is_add) { int ret; int s; struct Ip_arpreq arpreq; ipcom_memset(&arpreq, 0, sizeof(struct Ip_arpreq)); arpreq.arp_flags = arp_flags; ret = ipcom_getsockaddrbyaddr(IP_AF_LINK, str_link_addr, (struct Ip_sockaddr *) &arpreq.arp_ha); if (ret < 0 || arpreq.arp_ha.sdl_alen != IPNET_ETH_ADDR_SIZE) { if (silent == IP_FALSE) ipcom_printf("arp: '%s' is not a valid link address."IP_LF, str_link_addr); goto errout; } arpreq.arp_ha.sdl_type = IP_IFT_ETHER; arpreq.arp_ha.sdl_index = (Ip_u16) ifindex; ret = ipcom_getsockaddrbyaddr(IP_AF_INET, str_ip4_addr, &arpreq.arp_pa); if (ret < 0) { if (silent == IP_FALSE) ipcom_printf("arp: '%s' is not a valid IPv4 address."IP_LF, str_ip4_addr); goto errout; } s = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0); ret = ipcom_socketioctl(s, is_add ? IP_SIOCSARP : IP_SIOCUARP, &arpreq); ipcom_socketclose(s); if (ret < 0) goto errout; return 0; errout: return -ipcom_errno; } /* *=========================================================================== * ipnet_arp_print_usage *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipnet_arp_print_usage(void) { ipcom_printf(IP_LF "NAME"IP_LF " arp - address resolution display and control"IP_LF IP_LF); ipcom_printf("SYNOPSIS"IP_LF " arp [-silent] [-V ] [-i ] -a"IP_LF " arp [-silent] [-V ] [-i ] -A"IP_LF " arp [-silent] [-V ] [-i ] -F"IP_LF " arp [-silent] [-V ] [-i ] -d "IP_LF " arp [-silent] [-V ] [-i ] [-p] [-t] -s "IP_LF " arp [-silent] [-V ] [-i ] -r "IP_LF " arp [-silent] [-V ] [-i ] -u "IP_LF IP_LF); ipcom_printf("DESCRIPTION"IP_LF " The arp program displays and modifies the Internet-to-Ethernet address"IP_LF " translation tables used by the address resolution protocol."IP_LF IP_LF " Options:"IP_LF " -silent Suppress output. MUST be the first argument."IP_LF " -i Specify interface. First one if not specified."IP_LF " -t Temporary ARP entry."IP_LF " -p Public ARP entry (i.e. proxy ARP entry)."IP_LF " -V Specify route table. 0 if not specified."IP_LF IP_LF); ipcom_printf(" Commands:"IP_LF " -a Display the currently existing ARP entries."IP_LF " -A Delete all the ARP entries."IP_LF " -F Delete all the non-permanent ARP entries."IP_LF " -d Delete specified ARP entry."IP_LF " -s Register a ARP entry for a node."IP_LF " -r Send an ARP request to the host address."IP_LF " -u Send an unsolicited ARP response."IP_LF); } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_cmd_arp *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipnet_cmd_arp(int argc, char **argv) { int c, ret = 17; Ip_u32 ifindex = 0; #if IPCOM_VR_MAX > 1 int vr = ipcom_proc_vr_get(); int vr_new = vr; #endif Ipcom_getopt opt; int arp_flags = IP_ATF_PERM; Ip_bool silent = IP_FALSE; Ip_bool all_neighbors = IP_FALSE; int opt_mask = 0; if (argc > 1) { if (ipcom_strcmp(argv[1], "-silent") == 0) { silent = IP_TRUE; argc--; argv++; } } /* Parse options */ ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "aAFd:si:V:vtpgr:u", &opt)) != -1) { switch (c) { #if IPCOM_VR_MAX > 1 case 'V' : vr_new = ipcom_atoi(opt.optarg); break; #endif case 'i' : ifindex = ipcom_if_nametoindex(opt.optarg); if(ifindex == 0) { if (silent == IP_FALSE) ipcom_printf("arp: %s is not a valid interface."IP_LF, opt.optarg); goto done; } break; case 't': IP_BIT_CLR(arp_flags, IP_ATF_PERM); break; case 'p': IP_BIT_SET(arp_flags, IP_ATF_PUBL); break; case 'g': IP_BIT_SET(arp_flags, IP_ATF_GRAT); break; case 'v': all_neighbors = IP_TRUE; break; default: break; } } #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr_new); #endif /* Parse commands */ ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "aAFd:si:V:vtpgr:u", &opt)) != -1) { switch (c) { case 'a': ret = ipnet_cmd_neigh_for_each(IP_AF_INET, ifindex, all_neighbors, ipnet_arp_print_entry); goto done; case 'A': ret = ipnet_cmd_neigh_for_each(IP_AF_INET, ifindex, all_neighbors, ipnet_arp_delete_cb); goto done; case 'F': /*Flush all non-permanent entries.*/ IP_BIT_SET(opt_mask, IP_ARPOPT_NONPERM); ret = ipnet_cmd_neigh_for_each_optmask(IP_AF_INET, ifindex, all_neighbors, opt_mask, ipnet_arp_delete_cb); goto done; case 'd': ret = ipnet_arp_delete_entry(silent, ifindex, opt.optarg); goto done; case 'r': ret = ipnet_arp_force_probe(silent, ifindex, opt.optarg); goto done; case 's': case 'u': if (argc < opt.optind + 2) goto done; ret = ipnet_arp_add_entry(silent, argv[opt.optind], /* host addr */ argv[opt.optind+1], /* Ether addr */ ifindex, arp_flags, c == 's'); goto done; default: break; } } done: if (ret == 17 && silent == IP_FALSE) ipnet_arp_print_usage(); if (ret < 0 && silent == IP_FALSE) ipcom_printf("arp: operation failed, errno: %s" IP_LF, ipcom_strerror(-ret)); #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr); #endif return ret; } #endif /* IPCOM_USE_INET */ /* **************************************************************************** * END OF FILE **************************************************************************** */