Files
m241Neelima/components/ip_net2-6.9/ipnet2/src/ipnet_cmd_arp.c
T
2026-07-30 11:19:44 +05:30

516 lines
17 KiB
C

/*
******************************************************************************
* 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 <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 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 <ipcom_clib.h>
#include <ipcom_cmd.h>
#include <ipcom_getopt.h>
#include <ipcom_sysctl.h>
#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 <routetab>] [-i <ifname>] -a"IP_LF
" arp [-silent] [-V <routetab>] [-i <ifname>] -A"IP_LF
" arp [-silent] [-V <routetab>] [-i <ifname>] -F"IP_LF
" arp [-silent] [-V <routetab>] [-i <ifname>] -d <hostaddress>"IP_LF
" arp [-silent] [-V <routetab>] [-i <ifname>] [-p] [-t] -s <hostaddress> <ether_addr>"IP_LF
" arp [-silent] [-V <routetab>] [-i <ifname>] -r <hostaddress>"IP_LF
" arp [-silent] [-V <routetab>] [-i <ifname>] -u <peeraddress> <ether_addr>"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 <ifname> 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 <routetab> 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
****************************************************************************
*/