/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: iplite_cmd_arp.c,v $ $Revision: 1.23 $ * $Source: /home/interpeak/CVSRoot/iplite2/src/iplite_cmd_arp.c,v $ * $Author: lob $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifndef IPCOM_KERNEL #define IPCOM_KERNEL #endif #include "iplite_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #ifdef IPCOM_USE_INET #define IPCOM_USE_CLIB_PROTO #include #include #include "iplite_h.h" #include "iplite_eth.h" #include "iplite_cmd.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ IP_PUBLIC int iplite_cmd_arp(int argc, char **argv); IP_STATIC int iplite_arp_add_entry(IP_CONST char *str_ip4_addr, IP_CONST char *str_link_addr, Ip_u32 ifindex); /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * iplite_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 iplite_arp_print_entry(Iplite_netif *netif, Iplite_arp_entry *entry) { char str_addr[IPLITE_ETH_ADDR_SIZE * 3]; struct Ip_in_addr ina; char buf[128]; ina.s_addr = entry->ipaddr_n; if (ipcom_inet_ntop(IP_AF_INET, &ina, str_addr, sizeof(str_addr)) == IP_NULL) { return -ipcom_errno; } ipcom_sprintf(buf, "%16s", str_addr); ipcom_sprintf(buf + 16, " at %s [%s]"IP_LF, iplite_cmd_hwaddr_to_str((Ip_u8 *) entry->state.valid.ethaddr, sizeof (entry->state.valid.ethaddr), str_addr, sizeof (str_addr)), netif->ipcom.name); IPLITE_CODE_UNLOCK(); ipcom_printf(buf); IPLITE_CODE_LOCK(); return 0; } /* *=========================================================================== * iplite_arp_for_each *=========================================================================== * Description: Lists all ARP entries and call the callback function for each. * Parameters: ifindex - The interface specified at the command prompt. * cb - The callback function to call. * Returns: 0 == success, <0 == error * */ IP_STATIC int iplite_arp_for_each(Ip_u32 ifindex, int (*cb)(Iplite_netif *netif, Iplite_arp_entry *entry)) { int i; int j; Iplite_arp_entry *entry; Iplite_netif *netif; IPLITE_CODE_LOCK(); for(i = 1; i < IPLITE_CONF_MAX_NETIF; i++) { netif = iplite.netifs[i]; if(netif == IP_NULL) continue; if(netif->eth == IP_NULL) continue; if(ifindex && ifindex != (Ip_u32)i) continue; /* List the ARP cache. */ for (j = 0; j < IPLITE_ARP_MAX_CACHE; j++) { entry = netif->eth->arp_cache[j]; if (entry != IP_NULL) (void)cb(netif, entry); } } IPLITE_CODE_UNLOCK(); return 0; } /* *=========================================================================== * iplite_arp_delete_entry *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int iplite_arp_delete_entry(Iplite_netif *netif, Iplite_arp_entry *entry) { int i; for (i = 0; i < IPLITE_ARP_MAX_CACHE; i++) { if (netif->eth->arp_cache[i] == entry) { iplite_kfree(entry); netif->eth->arp_cache[i] = IP_NULL; break; } } return 0; } /* *=========================================================================== * iplite_arp_add_entry *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int iplite_arp_add_entry(IP_CONST char *str_ip4_addr, IP_CONST char *str_link_addr, Ip_u32 ifindex) { struct Ip_in_addr ina; Ip_u8 ethaddr[IPLITE_ETH_ADDR_SIZE]; Iplite_netif *netif; int i = 0; Iplite_arp_entry **arp_entry; int ret = 0; char macstr[30]; /* 6*4+5+1 */ char *str; char *endptr; char *tmp; Ip_u32 n; ipcom_strncpy(macstr, str_link_addr, sizeof(macstr) - 1); macstr[sizeof(macstr) - 1] = '\0'; ret = ipcom_inet_pton(IP_AF_INET, str_ip4_addr, &ina); if (ret < 0) return -ipcom_errno; if (ret == 0) return -IP_ERRNO_EINVAL; /* Invalid IPv4 address */ str = ipcom_strtok_r(macstr, ":", &tmp); while (str != IP_NULL) { n = ipcom_strtol(str, &endptr, 16); if (*endptr != '\0') return -IP_ERRNO_EINVAL; /* Trailing garbage in hex-number */ ethaddr[i] = (Ip_u8) n; i++; str = ipcom_strtok_r(IP_NULL, ":", &tmp); } if (i != IPLITE_ETH_ADDR_SIZE) return -IP_ERRNO_EINVAL; IPLITE_CODE_LOCK(); if (ifindex == 0) netif = iplite_ip4_get_netif(ina.s_addr, IP_NULL); else netif = iplite.netifs[ifindex]; if (netif == IP_NULL) { ret = -IP_ERRNO_EINVAL; goto errout; } do { arp_entry = &netif->eth->arp_cache[i]; i++; } while (*arp_entry != IP_NULL && i < IPLITE_ARP_MAX_CACHE); if (i >= IPLITE_ARP_MAX_CACHE) { ret = -IP_ERRNO_ENOBUFS; goto errout; } *arp_entry = iplite_kmalloc(sizeof(Iplite_arp_entry)); if (*arp_entry == IP_NULL) { ret = -IP_ERRNO_ENOMEM; goto errout; } (*arp_entry)->ipaddr_n = ina.s_addr; (*arp_entry)->state.valid.enddate = IPLITE_ARP_TIMEOUT_PERMANENT; ipcom_memcpy((*arp_entry)->state.valid.ethaddr, ethaddr, IPLITE_ETH_ADDR_SIZE); ret = 0; errout: IPLITE_CODE_UNLOCK(); return ret; } /* *=========================================================================== * iplite_cmd_arp_get_entry_from_addr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int iplite_cmd_arp_get_entry_from_addr(char *str_addr, Iplite_netif **matching_if, Iplite_arp_entry **matching_entry) { struct Ip_in_addr ina; Iplite_arp_entry *entry = IP_NULL; Iplite_netif *netif = IP_NULL; int i = 1; int j; if (ipcom_inet_pton (IP_AF_INET, str_addr, &ina) < 0) { return -ipcom_errno; } while (i < IPLITE_CONF_MAX_NETIF && entry == IP_NULL) { netif = iplite.netifs[i]; i++; if (netif == IP_NULL) continue; if (netif->eth == IP_NULL) continue; for (j = 0; j < IPLITE_ARP_MAX_CACHE; j++) { entry = netif->eth->arp_cache[j]; if (entry != IP_NULL && entry->ipaddr_n == ina.s_addr) break; else entry = IP_NULL; } } if (entry != IP_NULL) { *matching_if = netif; *matching_entry = entry; return 0; } else { return -IP_ERRNO_ENXIO; } } /* *=========================================================================== * iplite_arp_print_usage *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void iplite_arp_print_usage(void) { ipcom_printf(IP_LF); ipcom_printf("NAME"IP_LF); ipcom_printf(" arp - address resolution display and control"IP_LF); ipcom_printf(IP_LF); ipcom_printf("SYNOPSIS"IP_LF); ipcom_printf(" arp [-i ] -a"IP_LF); ipcom_printf(" arp [-i ] -A"IP_LF); ipcom_printf(" arp -d hostaddress"IP_LF); ipcom_printf(" arp [-i ] -s nodeaddress ether_addr"IP_LF); ipcom_printf(IP_LF); ipcom_printf("DESCRIPTION"IP_LF); ipcom_printf(" The arp program displays and modifies the Internet-to-Ethernet address"IP_LF); ipcom_printf(" translation tables used by the address resolution protocol."IP_LF); ipcom_printf(IP_LF); ipcom_printf(" Options:"IP_LF); ipcom_printf(" -i Specify interface. First one if not specified."IP_LF); ipcom_printf(IP_LF); ipcom_printf(" Commands:"IP_LF); ipcom_printf(" -a Display the currently existing ARP entries."IP_LF); ipcom_printf(" -A Erase all the ARP entries."IP_LF); ipcom_printf(" -d Delete specified ARP entry."IP_LF); ipcom_printf(" -s Register a ARP entry for a node."IP_LF); ipcom_printf(IP_LF); } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * iplite_cmd_arp *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int iplite_cmd_arp(int argc, char **argv) { int c, ret = 17; Ip_u32 ifindex = 0; Ipcom_getopt opt; /* Parse options */ ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "aAd:si:", &opt)) != -1) { switch (c) { case 'i' : ifindex = ipcom_if_nametoindex(opt.optarg); if (ifindex == 0) { ipcom_printf("arp: %s is not a valid interface."IP_LF, opt.optarg); goto done; } break; default: break; } } /* Parse commands */ ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "aAd:si:", &opt)) != -1) { switch (c) { case 'a': ret = iplite_arp_for_each(ifindex, iplite_arp_print_entry); goto done; case 'A': ret = iplite_arp_for_each(ifindex, iplite_arp_delete_entry); goto done; case 'd': { Iplite_arp_entry *entry; Iplite_netif *netif; ret = iplite_cmd_arp_get_entry_from_addr(opt.optarg, &netif, &entry); if (ret == 0) { IPLITE_CODE_LOCK(); ret = iplite_arp_delete_entry(netif, entry); IPLITE_CODE_UNLOCK(); } } goto done; case 's': if (argc < opt.optind + 2) goto done; ret = iplite_arp_add_entry(argv[opt.optind], argv[opt.optind+1], ifindex); goto done; case 'i' : case 'V' : default: break; } } done: if (ret == 17) iplite_arp_print_usage(); if (ret < 0) ipcom_printf("arp: operation failed, errno: %s" IP_LF, ipcom_strerror(-ret)); ipcom_printf(IP_LF); return ret; } #endif /* IPCOM_USE_INET */ /* **************************************************************************** * END OF FILE **************************************************************************** */