487 lines
13 KiB
C
487 lines
13 KiB
C
/*
|
|
******************************************************************************
|
|
* 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 <kenneth@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 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 <ipcom_clib.h>
|
|
#include <ipcom_getopt.h>
|
|
|
|
#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 <ifname>] -a"IP_LF);
|
|
ipcom_printf(" arp [-i <ifname>] -A"IP_LF);
|
|
ipcom_printf(" arp -d hostaddress"IP_LF);
|
|
ipcom_printf(" arp [-i <ifname>] -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 <ifname> 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
|
|
****************************************************************************
|
|
*/
|
|
|