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

676 lines
20 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmcp_cmd.c,v $ $Revision: 1.16 $
* $Source: /home/interpeak/CVSRoot/ipmcp/src/ipmcp_cmd.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* Shows statistics about multicast interfaces and multicast routes.
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmcp_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_getopt.h>
#include <ipcom_ipd.h>
#include <ipcom_sock.h>
#include <ipcom_type.h>
#ifdef IPMCP_USE_MLD
#include <ipcom_sock6.h>
#endif
#include "ipmcp_mcast.h"
#include "ipmcp_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMCP_CMD_SHOW_IF_STAT 1
#define IPMCP_CMD_SHOW_RT_STAT 2
#define IPMCP_CMD_SHOW_JG_STAT 3
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
IP_PUBLIC int ipmcp_cmd(int argc, char **argv);
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmcp_cmd_link_state_to_str
*===========================================================================
* Description: Returns a string representation of the link state.
* Parameters:
* Returns:
*
*/
IP_STATIC IP_CONST char *
ipmcp_cmd_link_state_to_str(int state)
{
switch (state)
{
case IPMCP_LINK_STATE_INACTIVE:
return "INACTIVE";
case IPMCP_LINK_STATE_NON_QUERIER:
return "NON-QUERIER";
case IPMCP_LINK_STATE_QUERIER:
return "QUERIER";
default:
IP_PANIC();
return "unknown state";
}
}
/*
*===========================================================================
* ipmcp_cmd_show_maddr_source_addr_cb
*===========================================================================
* Description: Prints one multicast source address.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_maddr_source_addr_cb(Ipmcp_saddr_t *saddr, const char *prefix)
{
char addrstr[IPMCP_ADDRSTRLEN];
ipcom_printf("%s%-20s %u" IP_LF, prefix,
ipcom_inet_ntop(saddr->maddr->domain,
saddr->ops->get_addr(saddr),
addrstr,
sizeof(addrstr)),
ipcom_tmo2_get(&saddr->timer) / 1000);
}
/*
*===========================================================================
* ipmcp_cmd_show_joined_groups_cb
*===========================================================================
* Description: Prints one joined multicast group.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_joined_groups_cb(Ipmcp_maddr_t *maddr, void *unused)
{
char addrstr[IPMCP_ADDRSTRLEN];
char *set_indent = "\t\t";
(void) unused;
ipcom_printf("\t%s%-19s %s %u" IP_LF,
maddr->domain == IP_AF_INET6 ? " " : "",
ipcom_inet_ntop(maddr->domain, maddr->ops->get_addr(maddr), addrstr, sizeof(addrstr)),
maddr->mode_is_include ? "INCLUDE" : "EXCLUDE",
ipcom_tmo2_get(&maddr->group_timer) / 1000);
ipcom_printf("%sInclude set:" IP_LF, set_indent);
ipcom_hash_for_each(maddr->include_set,
(Ipcom_hash_foreach_cb_func) ipmcp_cmd_show_maddr_source_addr_cb,
set_indent);
ipcom_printf("%sExclude set:" IP_LF, set_indent);
ipcom_hash_for_each(maddr->exclude_set,
(Ipcom_hash_foreach_cb_func) ipmcp_cmd_show_maddr_source_addr_cb,
set_indent);
}
#ifdef IPMCP_USE_IGMP
/*
*===========================================================================
* ipmcp_cmd_show_inet_ifs
*===========================================================================
* Description: Shows all the IPv4 multicast intefaces.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet_ifs(void)
{
struct Ip_sioc_vif_req vif_req;
char ifname[IP_IFNAMSIZ];
Ipmcp_netif_t *netif;
vif_req.vifi = ipmcp.upstream_if.igmp.vif_index;
if (ipcom_socketioctl(ipmcp.igmp.fd, IP_SIOCGETVIFCNT, &vif_req) < 0)
{
ipcom_printf("ioctl IP_SIOCGETVIFCNT failed for upstream interface: %s" IP_LF,
ipcom_strerror(ipcom_errno));
return;
}
ipcom_printf("Upstream interface IPv4 statistics"IP_LF);
ipcom_printf("\t%-16s%-10s%-10s"IP_LF, "Name", "Pkts", "Bytes");
ipcom_printf("\t%-16s%-10d%-10d"IP_LF,
ipcom_if_indextoname(ipmcp.upstream_if.ifindex, ifname),
vif_req.icount,
vif_req.ibytes);
ipcom_printf("Downstream interface IPv4 statistics"IP_LF);
ipcom_printf("\t%-16s%-10s%-10s%s"IP_LF, "Name", "Pkts", "Bytes", "State");
for (netif = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
netif;
netif = IPCOM_LIST_NEXT(&netif->list))
{
vif_req.vifi = netif->igmp.vif_index;
if (ipcom_socketioctl(ipmcp.igmp.fd, IP_SIOCGETVIFCNT, &vif_req) < 0)
{
ipcom_printf("ioctl IP_SIOCGETVIFCNT failed for upstream interface: %s" IP_LF,
ipcom_strerror(ipcom_errno));
return;
}
ipcom_printf("\t%-16s%-10d%-10d%s"IP_LF,
netif->ifname,
vif_req.ocount,
vif_req.obytes,
ipmcp_cmd_link_state_to_str(netif->igmp.state));
}
}
/*
*===========================================================================
* ipmcp_cmd_show_inet_route_cb
*===========================================================================
* Description: Prints all routes to one IPv4 group.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet_route_cb(Ipmcp_igmp_upstream_maddr_t *maddr, void *unused)
{
char dst[IP_INET_ADDRSTRLEN];
char src[IP_INET_ADDRSTRLEN];
int i;
struct Ip_sioc_sg_req sg;
Ipmcp_netif_t *netif;
(void) unused;
if (&maddr->saddrs[0].s_addr == 0)
return;
ipmcp.log_buf[0] = '\0';
for (netif = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
netif;
netif = IPCOM_LIST_NEXT(&netif->list))
{
if (ipcom_hash_get(netif->igmp.maddr_head, &maddr->maddr))
{
if (ipmcp.log_buf[0] != '\0')
ipcom_strcat(ipmcp.log_buf, ", ");
ipcom_strcat(ipmcp.log_buf, netif->ifname);
}
}
for (i = 0; i < IPMCP_IGMP_MAX_SRC_ADDRS; i++)
{
if (maddr->saddrs[i].s_addr == IP_INADDR_ANY)
continue;
sg.src = maddr->saddrs[i];
sg.grp = maddr->maddr;
if (ipcom_socketioctl(ipmcp.igmp.fd, IP_SIOCGETSGCNT, &sg) < 0)
{
ipcom_printf("ioctl IP_SIOCGETSGCNT: %s" IP_LF,
ipcom_strerror(ipcom_errno));
return;
}
ipcom_printf("\t%-20s%-20s%-8d%-8d%s"IP_LF,
ipcom_inet_ntop(IP_AF_INET, &maddr->maddr, dst, sizeof(dst)),
ipcom_inet_ntop(IP_AF_INET, &maddr->saddrs[i], src, sizeof(src)),
sg.pktcnt,
sg.bytecnt,
ipmcp.log_buf);
}
}
/*
*===========================================================================
* ipmcp_cmd_show_inet_routes
*===========================================================================
* Description: Shows all the IPv4 multicast routes.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet_routes(void)
{
if (ipmcp.upstream_if.igmp.maddr_head)
{
ipcom_printf("IPv4 routes"IP_LF);
ipcom_printf("\t%-20s%-20s%-8s%-8s%s" IP_LF, "Group", "Source", "Pkt", "Bytes", "Dwnstr ifs");
ipcom_hash_for_each(ipmcp.upstream_if.igmp.maddr_head,
(Ipcom_hash_foreach_cb_func) ipmcp_cmd_show_inet_route_cb,
IP_NULL);
}
}
/*
*===========================================================================
* ipmcp_cmd_show_inet_joined_groups
*===========================================================================
* Description: Shows all the groups that joined by clients
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet_joined_groups(void)
{
Ipmcp_netif_t *netif;
for (netif = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
netif;
netif = IPCOM_LIST_NEXT(&netif->list))
{
ipcom_printf("IPv4 groups joined at %s"IP_LF, netif->ifname);
if (netif->igmp.maddr_head == IP_NULL || netif->igmp.maddr_head->elem == 0)
ipcom_printf("\tNone"IP_LF);
else
{
ipcom_printf("\t%-20s%-8s%s" IP_LF, "Group", "State", "Timer");
ipcom_hash_for_each(netif->igmp.maddr_head,
(Ipcom_hash_foreach_cb_func) ipmcp_cmd_show_joined_groups_cb,
IP_NULL);
}
}
}
#endif /* IPMCP_USE_IGMP */
#ifdef IPMCP_USE_MLD
/*
*===========================================================================
* ipmcp_cmd_show_inet6_ifs
*===========================================================================
* Description: Shows all the IPv6 multicast intefaces.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet6_ifs(void)
{
struct Ip_sioc_mif_req6 mif_req;
char ifname[IP_IFNAMSIZ];
Ipmcp_netif_t *netif;
mif_req.mifi = ipmcp.upstream_if.mld.mif_index;
if (ipcom_socketioctl(ipmcp.mld.mrt_fd, IP_SIOCGETMIFCNT_IN6, &mif_req) < 0)
{
ipcom_printf("ioctl IP_SIOCGETVIFCNT failed for upstream interface: %s" IP_LF,
ipcom_strerror(ipcom_errno));
return;
}
ipcom_printf("Upstream interface IPv6 statistics"IP_LF);
ipcom_printf("\t%-16s%-10s%-10s"IP_LF, "Name", "Pkts", "Bytes");
ipcom_printf("\t%-16s%-10d%-10d"IP_LF,
ipcom_if_indextoname(ipmcp.upstream_if.ifindex, ifname),
IP_U64_GETLO(mif_req.icount),
IP_U64_GETLO(mif_req.ibytes));
ipcom_printf("Downstream interface IPv6 statistics"IP_LF);
ipcom_printf("\t%-16s%-10s%-10s%s"IP_LF, "Name", "Pkts", "Bytes", "State");
for (netif = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
netif;
netif = IPCOM_LIST_NEXT(&netif->list))
{
mif_req.mifi = netif->mld.mif_index;
if (ipcom_socketioctl(ipmcp.mld.mrt_fd, IP_SIOCGETMIFCNT_IN6, &mif_req) < 0)
{
ipcom_printf("ioctl IP_SIOCGETVIFCNT failed for upstream interface: %s" IP_LF,
ipcom_strerror(ipcom_errno));
return;
}
ipcom_printf("\t%-16s%-10d%-10d%s"IP_LF,
netif->ifname,
IP_U64_GETLO(mif_req.ocount),
IP_U64_GETLO(mif_req.obytes),
ipmcp_cmd_link_state_to_str(netif->mld.state));
}
}
/*
*===========================================================================
* ipmcp_cmd_show_inet6_route_cb
*===========================================================================
* Description: Prints all routes to one IPv6 group.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet6_route_cb(Ipmcp_mld_upstream_maddr_t *maddr, void *unused)
{
char dst[IP_INET6_ADDRSTRLEN];
char src[IP_INET6_ADDRSTRLEN];
int i;
struct Ip_sioc_sg_req6 sg;
Ipmcp_netif_t *netif;
(void) unused;
if (IP_IN6_IS_ADDR_UNSPECIFIED(&maddr->saddrs[0]))
return;
ipcom_memset(&sg, 0, sizeof(sg));
sg.src.sin6_family = IP_AF_INET6;
IPCOM_SA_LEN_SET(&sg.src, sizeof(sg.src));
sg.grp.sin6_family = IP_AF_INET6;
IPCOM_SA_LEN_SET(&sg.grp, sizeof(sg.grp));
ipmcp.log_buf[0] = '\0';
for (netif = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
netif;
netif = IPCOM_LIST_NEXT(&netif->list))
{
if (ipcom_hash_get(netif->mld.maddr_head, &maddr->maddr))
{
if (ipmcp.log_buf[0] != '\0')
ipcom_strcat(ipmcp.log_buf, ", ");
ipcom_strcat(ipmcp.log_buf, netif->ifname);
}
}
for (i = 0; i < IPMCP_MLD_MAX_SRC_ADDRS; i++)
{
if (IP_IN6_IS_ADDR_UNSPECIFIED(&maddr->saddrs[i]))
continue;
sg.src.sin6_addr = maddr->saddrs[i];
sg.grp.sin6_addr = maddr->maddr;
if (ipcom_socketioctl(ipmcp.mld.mrt_fd, IP_SIOCGETSGCNT_IN6, &sg) < 0)
{
ipcom_printf("ioctl IP_SIOCGETSGCNT_IN6: %s" IP_LF,
ipcom_strerror(ipcom_errno));
return;
}
ipcom_printf("\t%-30s%-30s%-8d%-8d%s"IP_LF,
ipcom_inet_ntop(IP_AF_INET6, &maddr->maddr, dst, sizeof(dst)),
ipcom_inet_ntop(IP_AF_INET6, &maddr->saddrs[i], src, sizeof(src)),
IP_U64_GETLO(sg.pktcnt),
IP_U64_GETLO(sg.bytecnt),
ipmcp.log_buf);
}
}
/*
*===========================================================================
* ipmcp_cmd_show_inet6_routes
*===========================================================================
* Description: Shows all the IPv6 multicast routes.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet6_routes(void)
{
if (ipmcp.upstream_if.mld.maddr_head)
{
ipcom_printf("IPv6 routes"IP_LF);
ipcom_printf("\t%-30s%-30s%-8s%-8s%s" IP_LF, "Group", "Source", "Pkt", "Bytes", "Dwnstr ifs");
ipcom_hash_for_each(ipmcp.upstream_if.mld.maddr_head,
(Ipcom_hash_foreach_cb_func) ipmcp_cmd_show_inet6_route_cb,
IP_NULL);
}
}
/*
*===========================================================================
* ipmcp_cmd_show_inet6_joined_groups
*===========================================================================
* Description: Shows all the groups that joined by clients
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_inet6_joined_groups(void)
{
Ipmcp_netif_t *netif;
for (netif = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
netif;
netif = IPCOM_LIST_NEXT(&netif->list))
{
ipcom_printf("IPv6 groups joined at %s"IP_LF, netif->ifname);
if (netif->mld.maddr_head->elem == 0)
ipcom_printf("\tNone"IP_LF);
else
{
ipcom_printf("\t%-30s%s" IP_LF, "Group", "State");
ipcom_hash_for_each(netif->mld.maddr_head,
(Ipcom_hash_foreach_cb_func) ipmcp_cmd_show_joined_groups_cb,
IP_NULL);
}
}
}
#endif /* IPMCP_USE_MLD */
/*
*===========================================================================
* ipmcp_cmd_show_usage
*===========================================================================
* Description: Shows the usage of the multicast proxy shell command.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_cmd_show_usage(void)
{
ipcom_printf("Interpeak multicast proxy statistics"IP_LF
"usage: "IP_LF
" mcastproxy [-4|-6] <-i|-j|-r>"IP_LF
" -4 show IPv4 only (default both)"IP_LF
" -6 show IPv6 only (default both)"IP_LF
" -i show interface statistics"IP_LF
" -j show groups joined by clients"IP_LF
" -r show route statistics"IP_LF
IP_LF
);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmcp_cmd
*===========================================================================
* Description: Shell command that shows statistics
* Parameters:
* Returns:
*
*/
IP_PUBLIC int
ipmcp_cmd(int argc, char **argv)
{
Ipcom_getopt opt;
int domain = 0;
int cmd = IPMCP_CMD_SHOW_IF_STAT;
int c;
if (argc < 2)
{
ipmcp_cmd_show_usage();
return 0;
}
ipcom_getopt_clear_r(&opt);
while ((c = ipcom_getopt_r(argc, argv, "46ijr", &opt)) != -1)
{
switch(c)
{
case '4':
domain = IP_AF_INET;
break;
case '6':
domain = IP_AF_INET6;
break;
case 'i':
break;
case 'j':
cmd = IPMCP_CMD_SHOW_JG_STAT;
break;
case 'r':
cmd = IPMCP_CMD_SHOW_RT_STAT;
break;
default:
ipcom_printf("sockperf: unknown option %c"IP_LF, (char)c);
return -1;
}
}
(void)ipcom_mutex_lock(ipmcp.daemon_mutex);
if (ipcom_ipd_send(IPMCP_IPD_NAME, IPMCP_IPD_EVENT_WAIT_FOR_SHELL_CMD) != IPCOM_SUCCESS)
{
(void)ipcom_mutex_unlock(ipmcp.daemon_mutex);
ipcom_printf("The IPMCP daemon is not running"IP_LF);
return -1;
}
(void)ipcom_sem_wait(ipmcp.cmd_sem);
switch (cmd)
{
case IPMCP_CMD_SHOW_IF_STAT:
#ifdef IPMCP_USE_IGMP
if (domain == 0 || domain == IP_AF_INET)
ipmcp_cmd_show_inet_ifs();
#endif
#ifdef IPMCP_USE_MLD
if (domain == 0 || domain == IP_AF_INET6)
ipmcp_cmd_show_inet6_ifs();
#endif
break;
case IPMCP_CMD_SHOW_RT_STAT:
#ifdef IPMCP_USE_IGMP
if (domain == 0 || domain == IP_AF_INET)
ipmcp_cmd_show_inet_routes();
#endif
#ifdef IPMCP_USE_MLD
if (domain == 0 || domain == IP_AF_INET6)
ipmcp_cmd_show_inet6_routes();
#endif
break;
case IPMCP_CMD_SHOW_JG_STAT:
#ifdef IPMCP_USE_IGMP
if (domain == 0 || domain == IP_AF_INET)
ipmcp_cmd_show_inet_joined_groups();
#endif
#ifdef IPMCP_USE_MLD
if (domain == 0 || domain == IP_AF_INET6)
ipmcp_cmd_show_inet6_joined_groups();
#endif
break;
default:
break;
}
(void)ipcom_mutex_unlock(ipmcp.daemon_mutex);
return 0;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/