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

647 lines
21 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ndp.c,v $ $Revision: 1.50.10.3 $
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ndp.c,v $
* $Author: kenneth $
* $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_INET6
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cmd.h>
#include <ipcom_getopt.h>
#include "ipnet.h"
#include "ipnet_cmd.h"
#include "ipnet_ctrl.h"
#include "ipnet_h.h"
#include "ipnet_routesock.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipnet_ndp_expire_time_str
*===========================================================================
* Description:
* Parameters: expires - IPCOM_ADDR_INFINITE, or time in seconds until
* entry expiration
* str_expire - buffer to write string representing 'expires'
* into
* Returns: str_expire
*
*/
IP_STATIC IP_CONST char*
ipnet_ndp_expire_time_str(Ip_u32 expires, char *str_expire)
{
if (expires == (Ip_time_t)IPCOM_ADDR_INFINITE)
ipcom_sprintf(str_expire, "perm");
else
ipcom_sprintf(str_expire, "%u s", expires);
return str_expire;
}
/*
*===========================================================================
* ipnet_ndp_state_str
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC char
ipnet_ndp_state_str(Ipnet_nd_state_t status)
{
switch (status)
{
case IPNET_ND_REACHABLE:
return 'R';
case IPNET_ND_STALE:
return 'S';
case IPNET_ND_DELAY:
return 'D';
case IPNET_ND_PROBE:
return 'P';
default:
/* Incomplete */
return 'I';
}
}
/*
*===========================================================================
* ipnet_ndp_print_ndp_entry
*===========================================================================
* Description: Prints a NDP entry
* Parameters: rt - A NDP entry
* addrs - Addresses for this NDP entry.
* Returns: 0 = success, -1 = fail.
*
*/
IP_STATIC int
ipnet_ndp_print_entry(struct Ipnet_rt_msghdr *rt,
struct Ip_sockaddr *addrs[IPNET_RTAX_MAX])
{
struct Ipnet_tag_nc_entry tag;
char str[256];
int ret;
tag.hdr.type = IPNET_CTRL_GET_NC_ENTRY;
tag.hdr.size = sizeof(tag);
tag.ifindex = rt->rtm_index;
ipcom_memcpy(&tag.addr,
addrs[IPNET_RTAX_DST],
sizeof(tag.addr));
tag.vr_index = (Ip_u16) ipcom_proc_vr_get();
ret = ipnet_ctrl(&tag.hdr);
if (ret < 0)
return ret;
ipcom_printf("%-35s ",
ipcom_cmd_sockaddr_to_str((struct Ip_sockaddr *) &tag.addr,
IP_FALSE,
IP_TRUE,
str,
sizeof(str)));
ipcom_printf("%-18s ",
ipcom_cmd_sockaddr_to_str((struct Ip_sockaddr *) &tag.link_addr,
IP_FALSE,
IP_TRUE,
str,
sizeof(str)));
ipcom_printf("%-9s ", ipcom_if_indextoname(tag.ifindex, str));
ipcom_printf("%-7s ", ipnet_ndp_expire_time_str(tag.expires_sec, str));
ipcom_printf("%c", ipnet_ndp_state_str(tag.state));
ipcom_printf("\n");
return 0;
}
/*
*===========================================================================
* ipnet_ndp_delete_ndp_entry
*===========================================================================
* Description: Deletes a NDP entry.
* Parameters: silent - IP_TRUE to quench any output to stdout.
* ifindex - interface the NDP entry is assigned to
* str_ip6_addr - the IPv6 address of the NDP entry
* Returns: 0 = success, -1 == error
*
*/
IP_STATIC int
ipnet_ndp_delete_ndp_entry(Ip_bool silent,
Ip_u32 ifindex,
IP_CONST char *str_ip6_addr)
{
struct Ipnet_tag_nc_entry tag;
if (ipcom_getsockaddrbyaddrname(IP_AF_INET6,
IP_TRUE,
str_ip6_addr,
(struct Ip_sockaddr *) &tag.addr) < 0)
{
if (silent == IP_FALSE)
ipcom_printf("%s is not a valid IPv6 address\n", str_ip6_addr);
return -1;
}
tag.hdr.type = IPNET_CTRL_DEL_NC_ENTRY;
tag.hdr.size = sizeof(tag);
tag.vr_index = (Ip_u16) ipcom_proc_vr_get();
tag.ifindex = ifindex;
if (ipnet_ctrl(&tag.hdr) < 0)
{
if (silent == IP_FALSE)
ipcom_printf("Failed to delete %s: %s", str_ip6_addr, ipcom_strerror(ipcom_errno));
return -1;
}
return 0;
}
/*
*===========================================================================
* ipnet_ndp_delete_cb
*===========================================================================
* Description: Deletes a single NDP entry.
* Parameters: rt - An NDP entry.
* addrs - Addresses in the NDP entry.
* Returns: 0 == success, <0 == error
*
*/
IP_STATIC int
ipnet_ndp_delete_cb(struct Ipnet_rt_msghdr *rt,
struct Ip_sockaddr *addrs[IPNET_RTAX_MAX])
{
char addr_str[IP_INET6_ADDRSTRLEN];
struct Ip_sockaddr_in6 *in6;
in6 = (struct Ip_sockaddr_in6 *) addrs[IPNET_RTAX_DST];
return ipnet_ndp_delete_ndp_entry(IP_TRUE,
rt->rtm_index,
ipcom_inet_ntop(IP_AF_INET6,
&in6->sin6_addr,
addr_str,
sizeof(addr_str)));
}
/*
*===========================================================================
* ipnet_ndp_print_default_router_entries
*===========================================================================
* Description: Prints all default routers.
* Parameters: silent - IP_TRUE to suppress any output to stdout.
* Returns: 0 = success, -1 = fail.
*
*/
IP_STATIC int
ipnet_ndp_print_prefix_entries(Ip_bool silent)
{
if (silent == IP_FALSE)
{
struct Ipnet_tag_prefix_entry tag;
char str[44];
int ret;
ipcom_printf("%-40s%-10s%-8s\n", "Prefix", "Expire", "Netif");
tag.hdr.type = IPNET_CTRL_NEW_ENUM_PREFIX_ENTRY;
tag.hdr.size = sizeof(tag);
tag.ifindex = 0;
tag.vr_index = (Ip_u16) ipcom_proc_vr_get();
for (;;)
{
ret = ipnet_ctrl(&tag.hdr);
if (ret == IPNET_CTRL_ENUM_DONE)
break;
if (ret < 0)
{
ipcom_printf("ipnet_ctrl() failed to enumerate prefix entry: %s"IP_LF,
ipcom_strerror(ipcom_errno));
return -1;
}
tag.hdr.type = IPNET_CTRL_CONT_ENUM_PREFIX_ENTRY;
(void)ipcom_cmd_sockaddr_to_str((struct Ip_sockaddr *) &tag.prefix,
IP_FALSE, IP_FALSE, str, sizeof(str));
ipcom_sprintf(&str[ipcom_strlen(str)], "/%d", tag.bits);
ipcom_printf("%-39s ", str);
ipcom_printf("%-9s ", ipnet_ndp_expire_time_str(tag.expires_sec, str));
ipcom_printf("%-7s ", ipcom_if_indextoname(tag.ifindex, str));
ipcom_printf("\n");
}
}
return 0;
}
/*
*===========================================================================
* ipnet_ndp_print_default_router_entries
*===========================================================================
* Description: Prints all routers that has announced themself.
* Parameters: silent - IP_TRUE to suppress any output to stdout.
* Returns: 0 = success, -1 = fail.
*
*/
IP_STATIC int
ipnet_ndp_print_default_router_entries(Ip_bool silent)
{
if (silent == IP_FALSE)
{
struct Ipnet_tag_router_entry tag;
char str[IP_INET6_ADDRSTRLEN];
int ret;
ipcom_printf("%-36s%-10s%-8s\n", "Router address", "Expire", "Netif");
tag.hdr.type = IPNET_CTRL_NEW_ENUM_ROUTER_ENTRY;
tag.hdr.size = sizeof(tag);
tag.vr_index = (Ip_u16) ipcom_proc_vr_get();
for (;;)
{
ret = ipnet_ctrl(&tag.hdr);
if (ret == IPNET_CTRL_ENUM_DONE)
break;
if (ret < 0)
{
ipcom_printf("ipnet_ctrl() failed to get router entry: %s"IP_LF,
ipcom_strerror(ipcom_errno));
return -1;
}
tag.hdr.type = IPNET_CTRL_CONT_ENUM_ROUTER_ENTRY;
ipcom_printf("%-35s ", ipcom_inet_ntop(IP_AF_INET6, &tag.addr, str, sizeof(str)));
ipcom_printf("%-9s ", ipnet_ndp_expire_time_str(tag.expires_sec, str));
ipcom_printf("%-7s ", ipcom_if_indextoname(tag.ifindex, str));
ipcom_printf("\n");
}
}
return 0;
}
/*
*===========================================================================
* ipnet_ndp_remove_all_default_router_entries
*===========================================================================
* Description: Remove all default router entries.
* Parameters: silent - IP_TRUE to suppress any output to stdout.
* Returns: 0 = success, -1 = fail.
*
*/
IP_STATIC int
ipnet_ndp_remove_all_default_router_entries(Ip_bool silent)
{
struct Ipnet_tag_router_entry tag;
int ret;
tag.hdr.size = sizeof(tag);
tag.vr_index = (Ip_u16) ipcom_proc_vr_get();
for (;;)
{
tag.hdr.type = IPNET_CTRL_NEW_ENUM_ROUTER_ENTRY;
ret = ipnet_ctrl(&tag.hdr);
if (ret == IPNET_CTRL_ENUM_DONE)
break;
if (ret < 0)
{
if (silent == IP_FALSE)
ipcom_printf("ipnet_ctrl() failed to get router entry: %s"IP_LF,
ipcom_strerror(ipcom_errno));
return -1;
}
tag.hdr.type = IPNET_CTRL_DEL_ROUTER_ENTRY;
if (ipnet_ctrl(&tag.hdr) < 0)
{
if (silent == IP_FALSE)
ipcom_printf("ipnet_ctrl() failed to delete router entry: %s"IP_LF,
ipcom_strerror(ipcom_errno));
return -1;
}
}
return 0;
}
/*
*===========================================================================
* ipnet_ndp_add_entry
*===========================================================================
* Description: Adds a neighbor cache entry.
* Parameters: ifname - The name of the interface to a NC entry.
* str_ip6_addr - The address of the entry.
* str_link_addr - The link layer address.
* Returns: 0 = success, -1 = fail.
*
*/
IP_STATIC int
ipnet_ndp_add_entry(Ip_bool silent,
Ip_u32 ifindex,
IP_CONST char *str_ip6_addr,
IP_CONST char *str_link_addr)
{
struct Ipnet_tag_nc_entry tag;
char ifname[IP_IFNAMSIZ];
if (ifindex)
ipcom_if_indextoname(ifindex, ifname);
else
strncpy(ifname, "*unspecified*", IP_IFNAMSIZ);
if (ipcom_getsockaddrbyaddrname(IP_AF_INET6, IP_TRUE, str_ip6_addr,
(struct Ip_sockaddr *) &tag.addr) < 0)
{
if (silent == IP_FALSE)
ipcom_printf("%s is not a valid IPv6 address\n", str_ip6_addr);
goto errout;
}
tag.hdr.type = IPNET_CTRL_ADD_NC_ENTRY;
tag.hdr.size = sizeof(tag);
tag.ifindex = ifindex;
tag.is_router = IP_FALSE;
tag.expires_sec = IPCOM_ADDR_INFINITE;
tag.vr_index = (Ip_u16) ipcom_proc_vr_get();
if (ipcom_getsockaddrbyaddr(IP_AF_LINK,
str_link_addr,
(struct Ip_sockaddr *) &tag.link_addr) < 0)
{
if (silent == IP_FALSE)
ipcom_printf("%s is not a valid link address for %s\n",
str_link_addr,
(ipcom_if_indextoname(ifindex, ifname)
? ifname
: "<unknown>"));
return -1;
}
if (ipnet_ctrl(&tag.hdr) < 0)
{
if (silent == IP_FALSE)
ipcom_printf("Failed to add NC entry to %s\n",
(ipcom_if_indextoname(ifindex, ifname)
? ifname
: "<unknown>"));
goto errout;
}
return 0;
errout:
return -1;
}
/*
*===========================================================================
* ipnet_ndp_print_usage
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipnet_ndp_print_usage(void)
{
ipcom_printf(IP_LF);
ipcom_printf("NAME" IP_LF);
ipcom_printf(" ndp - control/diagnose IPv6 neighbor discovery protocol" IP_LF);
ipcom_printf(IP_LF);
ipcom_printf("SYNOPSIS" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] -a" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] -A" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] -c" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] [-i <ifname>] -d hostaddress" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] -p" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] -r" IP_LF);
ipcom_printf(" ndp [-silent] [-V <routetab>] -R" IP_LF);
ipcom_printf(" ndp [-silent] [[-V <routetab>] | [-i <ifname>]] -s nodeaddress ether_addr" IP_LF);
ipcom_printf(IP_LF);
ipcom_printf("DESCRIPTION" IP_LF);
ipcom_printf(" The ndp command manipulates the address mapping table used by Neighbor" IP_LF);
ipcom_printf(" Discovery Protocol (NDP). It can take up to 1 minute before deleted" IP_LF);
ipcom_printf(" entries is removed, but they should be shown as 'expired' immediately." IP_LF);
ipcom_printf(IP_LF);
ipcom_printf(" Options:"IP_LF);
ipcom_printf(" -silent Suppress output. MUST be first argument"IP_LF);
ipcom_printf(" -i <ifname> Specify interface. Selected by the stack otherwise."IP_LF);
ipcom_printf(" -V <routetab> Specify route table. <routetab> = 0 if not specified."IP_LF);
ipcom_printf(IP_LF);
ipcom_printf(" Commands:" IP_LF);
ipcom_printf(" -a Dump the currently existing NDP entries." IP_LF);
ipcom_printf(" -A Erase all NDP entries." IP_LF);
ipcom_printf(" -d Delete specified NDP entry." IP_LF);
ipcom_printf(" -p Show prefix list." IP_LF);
ipcom_printf(" -r Show the list of default routers added by the router advertisement protocol." IP_LF);
ipcom_printf(" -R Flush all default routers added by the router advertisement protocol." IP_LF);
ipcom_printf(" -s Register a NDP entry for a node. The entry will be permanent." IP_LF);
ipcom_printf(" Specify -V or -i, not both." IP_LF);
ipcom_printf("" IP_LF);
}
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipnet_cmd_ndp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC int
ipnet_cmd_ndp(int argc, char **argv)
{
#if IPCOM_VR_MAX > 1
Ip_u16 org_vr_index = (Ip_u16) ipcom_proc_vr_get();
Ip_u16 vr_index = org_vr_index;
#endif
Ip_u32 ifindex = 0;
Ip_bool silent = IP_FALSE;
int c;
int ret = 17;
Ipcom_getopt opt;
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, "AHPRad:hprsV:i:", &opt)) != -1)
{
switch (c)
{
case 'V' :
#if IPCOM_VR_MAX > 1
vr_index = (Ip_u16) ipcom_atoi(opt.optarg);
#endif
break;
case 'i' :
ifindex = ipcom_if_nametoindex(opt.optarg);
if(ifindex == 0)
{
if (silent == IP_FALSE)
ipcom_printf("%s is not a valid interface."IP_LF, opt.optarg);
goto done;
}
break;
default:
break;
}
}
#if IPCOM_VR_MAX > 1
ipcom_proc_vr_set(vr_index);
#endif
ipcom_getopt_clear_r(&opt);
while ((c = ipcom_getopt_r(argc, argv, "AHRad:hprsV:i:", &opt)) != -1)
{
switch (c)
{
case 'a':
ipcom_printf("%-35s %-18s %-9s %-7s %-4s\n",
"Neighbor",
"Linklayer Address",
"Netif",
"Expire",
"St");
ret = ipnet_cmd_neigh_for_each(IP_AF_INET6,
ifindex,
IP_TRUE,
ipnet_ndp_print_entry);
break;
case 'A':
ret = ipnet_cmd_neigh_for_each(IP_AF_INET6,
ifindex,
IP_TRUE,
ipnet_ndp_delete_cb);
break;
case 'd':
ret = ipnet_ndp_delete_ndp_entry(silent, ifindex, opt.optarg);
break;
case 'p':
ret = ipnet_ndp_print_prefix_entries(silent);
break;
case 'R':
ret = ipnet_ndp_remove_all_default_router_entries(silent);
break;
case 'r':
ret = ipnet_ndp_print_default_router_entries(silent);
break;
case 's':
if (argc < opt.optind + 2)
goto done;
ret = ipnet_ndp_add_entry(silent, ifindex, argv[opt.optind], argv[opt.optind+1]);
break;
default:
break;
}
}
done:
#if IPCOM_VR_MAX > 1
ipcom_proc_vr_set(org_vr_index);
#endif
if (ret == 17 && silent == IP_FALSE)
ipnet_ndp_print_usage();
return ret;
}
#endif /* IPCOM_USE_INET6 */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/