original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
+902
View File
@@ -0,0 +1,902 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmcp.c,v $ $Revision: 1.30.10.4 $
* $Source: /home/interpeak/CVSRoot/ipmcp/src/ipmcp.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 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_ipd.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_type.h>
#include <ipnet_routesock.h>
#include "ipmcp.h"
#include "ipmcp_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IPCOM_PROCESS(ipmcp_daemon);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
Ipmcp_data_t ipmcp;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmcp_if_destroy
*===========================================================================
* Description: Frees all resources held by the interface structure.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_if_destroy(Ipmcp_netif_t *netif)
{
if (netif == IP_NULL)
return;
#ifdef IPMCP_USE_IGMP
ipmcp_igmp_if_destroy(netif);
#endif
#ifdef IPMCP_USE_MLD
ipmcp_mld_if_destroy(netif);
#endif
ipcom_list_remove(&netif->list);
ipcom_free(netif);
}
/*
*===========================================================================
* ipmcp_if_create
*===========================================================================
* Description: Create interface descriptors for IPMCP
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipmcp_if_create(Ip_u32 ifindex)
{
Ipmcp_netif_t *netif;
int ret;
char ifname[IP_IFNAMSIZ];
char *downstream_if;
char *p = IP_NULL;
char *sep = ", ";
char *ds;
netif = ipmcp_if_find(ifindex);
if (netif)
/* Duplicate */
return -1;
if (ipcom_if_indextoname(ifindex, ifname) == IP_NULL)
{
IPCOM_LOG1(ERR, "ipmcp_if_create: could not get the name of the interface with index %d", ifindex);
return -1;
}
ds = ipcom_strdup(ipmcp.config.downstream_ifs);
if (ds == IP_NULL)
{
IPCOM_LOG1(ERR, "ipmcp_if_create: failed to duplicate string", ifindex);
return -1;
}
for (downstream_if = ipcom_strtok_r(ds, sep, &p);
downstream_if != IP_NULL;
downstream_if = ipcom_strtok_r(IP_NULL, sep, &p))
{
if (ipcom_strcmp(ifname, downstream_if) == 0)
break;
}
ipcom_free(ds);
if (downstream_if == IP_NULL)
{
IPCOM_LOG1(DEBUG, "ipmcp_if_create: interface %s is not a downstream interface, ignoring",
ifname);
return 0;
}
netif = ipcom_calloc(1, sizeof(Ipmcp_netif_t));
if (netif == IP_NULL)
{
IPCOM_LOG0(ERR, "ipmcp_if_create: failed to allocate memory");
return -1;
}
netif->ifindex = ifindex;
ipcom_strcpy(netif->ifname, ifname);
ipcom_list_insert_last(&ipmcp.downstream_ifs_head, &netif->list);
#ifdef IPMCP_USE_IGMP
ret = ipmcp_igmp_if_create(netif);
if (ret < 0)
goto cleanup;
#endif
#ifdef IPMCP_USE_MLD
ret = ipmcp_mld_if_create(netif);
if (ret < 0)
goto cleanup;
#endif
return 0;
cleanup:
ipmcp_if_destroy(netif);
return ret;
}
/*
*===========================================================================
* ipmcp_add_downstream_ifs
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipmcp_add_downstream_ifs(void)
{
struct Ip_if_nameindex *ifrs, *i;
struct Ip_ifreq ifreq;
int ret = -1;
ifrs = ipcom_if_nameindex();
for (i = ifrs; i && (i->if_name != IP_NULL); i++)
{
/* coverity[fixed_size_dest] : FALSE */
ipcom_strcpy(ifreq.ifr_name, i->if_name);
#ifdef IP_PORT_LAS
if (ipcom_socketioctl(ipmcp.cfg_fd, IP_SIOCGIFFLAGS, (char*)&ifreq) < 0)
#else
if (ipcom_socketioctl(ipmcp.ipd_fd, IP_SIOCGIFFLAGS, (char*)&ifreq) < 0)
#endif
{
IPCOM_LOG1(ERR, "ipcom_ioctl(SIOCGIFFLAGS) failed, errno = %d", ipcom_errno);
goto cleanup;
}
/* Skip loopback */
if (IP_BIT_ISSET(ifreq.ifr_ifru.ifru_flags, IP_IFF_LOOPBACK))
continue;
/* Skip if not multicast capable */
if (IP_BIT_ISFALSE(ifreq.ifr_ifru.ifru_flags, IP_IFF_MULTICAST))
continue;
/* Skip if DOWN */
if (IP_BIT_ISFALSE(ifreq.ifr_ifru.ifru_flags, IP_IFF_UP))
continue;
if (ipmcp_if_create(i->if_index) < 0)
goto cleanup;
}
ret = 0;
cleanup:
ipcom_if_freenameindex(ifrs);
return ret;
}
/*
*===========================================================================
* ipmcp_upstream_if_add
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipmcp_upstream_if_add(void)
{
struct Ip_ifreq ifreq;
Ip_size_t namsiz = sizeof(ifreq.ifr_name);
int ret;
if (ipcom_sysvar_get("ipmcp.UpstreamIf", ifreq.ifr_name, &namsiz) == IP_NULL)
{
IPCOM_LOG0(ERR, "missing 'ipmcp.UpstreamIf'");
IP_PANIC2();
return -1;
}
ipcom_strcpy(ipmcp.upstream_if.ifname, ifreq.ifr_name);
ipmcp.upstream_if.ifindex = ipcom_if_nametoindex(ifreq.ifr_name);
if (ipmcp.upstream_if.ifindex == 0)
{
IPCOM_LOG1(ERR, "upstream interface %s is not attached to the stack", ifreq.ifr_name);
IP_PANIC2();
return -1;
}
#ifdef IP_PORT_LAS
if (ipcom_socketioctl(ipmcp.cfg_fd, IP_SIOCGIFFLAGS, (char*)&ifreq) < 0)
#else
if (ipcom_socketioctl(ipmcp.ipd_fd, IP_SIOCGIFFLAGS, (char*)&ifreq) < 0)
#endif
{
IPCOM_LOG1(ERR, "ipcom_ioctl(SIOCGIFFLAGS) failed: %s", ipcom_strerror(ipcom_errno));
IP_PANIC();
return -1;
}
if (IP_BIT_ISSET(ifreq.ifr_ifru.ifru_flags, IP_IFF_LOOPBACK)
|| IP_BIT_ISFALSE(ifreq.ifr_ifru.ifru_flags, IP_IFF_MULTICAST))
{
IPCOM_LOG1(ERR,
"%s cannot be used as uplink interface, must not be loopback and must be multicast capable",
ifreq.ifr_name);
IP_PANIC2();
return -1;
}
if (IP_BIT_ISSET(ifreq.ifr_ifru.ifru_flags, IP_IFF_UP))
ipmcp.state = IPMCP_STATE_RUNNING;
else
{
IPCOM_LOG1(NOTICE,
"%s was found, but is currently not UP, enter WAITING state",
ifreq.ifr_name);
ipmcp.state = IPMCP_STATE_WAITING;
}
#ifdef IPMCP_USE_IGMP
ret = ipmcp_igmp_upstream_if_create(&ipmcp.upstream_if);
if (ret < 0)
return ret;
#endif
#ifdef IPMCP_USE_MLD
ret = ipmcp_mld_upstream_if_create(&ipmcp.upstream_if);
if (ret < 0)
return ret;
#endif
return 0;
}
/*
*===========================================================================
* ipmcp_upstream_if_destroy
*===========================================================================
* Description: Removes the upstream interface.
* Parameters:
* Returns: 0 = success, <0 = error.
*
*/
IP_STATIC void
ipmcp_upstream_if_destroy(void)
{
#ifdef IPMCP_USE_IGMP
ipmcp_igmp_upstream_if_destroy(&ipmcp.upstream_if);
#endif
#ifdef IPMCP_USE_MLD
ipmcp_mld_upstream_if_destroy(&ipmcp.upstream_if);
#endif
}
/*
*===========================================================================
* ipmcp_apply_configuration
*===========================================================================
* Description: Setup the system according to the configuration.
* Parameters:
* Returns: 0 = success, <0 = error.
*
*/
IP_STATIC int
ipmcp_setup_configuration(void)
{
Ipmcp_conf_t *conf = &ipmcp.config;
if (ipmcp_upstream_if_add() < 0)
return -1;
/* Read sysvar configuration. */
conf->robustness_variable = (Ip_u32)ipcom_sysvar_get_as_int("ipmcp.RobustnessVariable", 2);
if (conf->robustness_variable == 0 || conf->robustness_variable == 0xffffffff)
{
IPCOM_LOG0(ERR, "invalid 'ipmcp.RobustnessVariable'");
return -1;
}
conf->query_interval = (Ip_u32)ipcom_sysvar_get_as_int("ipmcp.QueryInterval", 125);
if (conf->query_interval > 0xffffffff / 1000)
{
IPCOM_LOG1(ERR, "No support for query intervals > %u 'ipmcp.QueryInterval'", 0xffffffff / 1000);
return -1;
}
conf->query_interval *= 1000; /* milliseconds */
conf->query_response_interval =
(Ip_u16)ipcom_sysvar_get_as_int("ipmcp.QueryResponseInterval", 10000);
conf->last_member_query_interval =
(Ip_u32)ipcom_sysvar_get_as_int("ipmcp.LastMemberQueryInterval", 1000);
conf->last_member_query_count =
(Ip_u32)ipcom_sysvar_get_as_int("ipmcp.LastMemberQueryCount", conf->robustness_variable);
/* Calculate some parameters */
conf->startup_query_interval =
(Ip_u32)ipcom_sysvar_get_as_int("ipmcp.StartupQueryInterval", 0) * 1000;
if (conf->startup_query_interval == 0)
conf->startup_query_interval = conf->query_interval / 4;
conf->startup_query_count = conf->robustness_variable;
ipmcp.config.downstream_ifs = ipcom_sysvar_get("ipmcp.DownstreamIfs", IP_NULL, IP_NULL);
if (ipmcp.config.downstream_ifs == IP_NULL)
{
IPCOM_LOG0(ERR, "missing 'ipmcp.DownstreamIfs'");
return -1;
}
return ipmcp_add_downstream_ifs();
}
/*
*===========================================================================
* ipmcp_teardown_configuration
*===========================================================================
* Description: Frees all resouces that is tied to the current configuration.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_teardown_configuration(void)
{
Ipmcp_netif_t *i;
ipmcp.state = IPMCP_STATE_HALTED;
for (i = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
i != IP_NULL;
i = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head))
{
ipmcp_if_destroy(i);
}
ipmcp_upstream_if_destroy();
ipcom_free(ipmcp.config.downstream_ifs);
}
/*
*===========================================================================
* ipmcp_init
*===========================================================================
* Description: Initializes the multicast proxy.
* Parameters:
* Returns: 0 = success, <0 = error.
*
*/
IP_STATIC int
ipmcp_init(void)
{
int ret;
Ip_err err = IPCOM_ERR_FAILED;;
ipcom_list_init(&ipmcp.downstream_ifs_head);
ipmcp.tmo_head = ipcom_tmo2_new();
if (ipmcp.tmo_head == IP_NULL)
{
IPCOM_LOG0(ERR, "Failed to create timeout head");
goto done;
}
ipmcp.rt_fd = ipcom_socket(IP_AF_ROUTE, IP_SOCK_RAW, 0);
if (ipmcp.rt_fd == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipcom_socket(ROUTE,RAW) failed: %s", ipcom_strerror(ipcom_errno));
goto done;
}
#ifdef IP_PORT_LAS
ipmcp.cfg_fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
if (ipmcp.cfg_fd == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipcom_socket(INET,DGRAM) failed: %s", ipcom_strerror(ipcom_errno));
goto done;
}
#endif
#ifdef IPMCP_USE_IGMP
if (0 > (ret = ipmcp_igmp_init()))
return ret;
#endif
#ifdef IPMCP_USE_MLD
if (0 > (ret = ipmcp_mld_init()))
return ret;
#endif
err = IPCOM_SUCCESS;;
done:
if (ipcom_ipd_init(IPMCP_IPD_NAME, err, &ipmcp.ipd_fd) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "Failed to initialize IPD: %s", ipcom_strerror(ipcom_errno));
return -1;
}
return 0;
}
/*
*===========================================================================
* ipmcp_exit
*===========================================================================
* Description: Frees all resources held by the daemon.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmcp_exit(void)
{
(void)ipcom_ipd_exit("ipmcp", ipmcp.ipd_fd);
(void)ipcom_socketclose(ipmcp.rt_fd);
#ifdef IP_PORT_LAS
(void)ipcom_socketclose(ipmcp.cfg_fd);
#endif
#ifdef IPMCP_USE_IGMP
ipmcp_igmp_exit();
#endif
#ifdef IPMCP_USE_MLD
ipmcp_mld_exit();
#endif
ipcom_tmo2_delete(ipmcp.tmo_head);
ipmcp_is_enabled = IP_FALSE;
}
/*
*===========================================================================
* ipmcp_ipd_input
*===========================================================================
* Description: Processes IPD messages,
* Parameters: fd - The IPD socket
* done - Will be set to true if the daemon should shutdown.
* Returns: 0 = Daemon will continue and process other messages.
* 1 = The daemon must reconfigure itsef.
*
*/
IP_STATIC int
ipmcp_ipd_input(int fd, Ip_bool *done)
{
switch (ipcom_ipd_input(fd))
{
case IPCOM_IPD_EVENT_RECONFIGURE:
IPCOM_LOG0(INFO, "received IPD reconfigure message");
*done = IP_FALSE;
return 1;
case IPCOM_IPD_EVENT_KILL:
IPCOM_LOG0(INFO, "received IPD kill message");
*done = IP_TRUE;
return 1;
case IPMCP_IPD_EVENT_WAIT_FOR_SHELL_CMD:
/* Notify the shell command that the MCP daemon now waiting
here */
(void)ipcom_sem_post(ipmcp.cmd_sem);
/* This will block this task until the shell command has
finished reading the state of the MCP daemon */
(void)ipcom_mutex_lock(ipmcp.daemon_mutex);
(void)ipcom_mutex_unlock(ipmcp.daemon_mutex);
return 0;
default:
return 0;
}
}
/*
*===========================================================================
* ipmcp_route_input
*===========================================================================
* Description: Processes route socket messages.
* Parameters: fd - The route socket
* Returns: 0 = success
* <0 = error
*
*/
IP_STATIC int
ipmcp_route_input(int fd)
{
Ipmcp_netif_t *netif;
int length;
union rtmsg_union
{
struct Ipnet_rt_msghdr rtmsg;
struct Ipnet_if_msghdr ifmsg;
struct Ipnet_ifa_msghdr ifamsg;
} buf;
/* Read routing message headers only (truncated read). */
length = ipcom_recv(fd, &buf, sizeof(buf), 0);
if (length == IP_SOCKERR)
{
IP_PANIC2();
IPCOM_LOG1(ERR, "ipmcp_route_input: ipcom_recv() failed, errno = %d", ipcom_errno);
return -1;
}
if (length < (int) sizeof(struct Ipnet_rs_msghdr))
{
IP_PANIC2();
IPCOM_LOG2(ERR, "ipmcp_route_input: ipcom_recv() failed, truncated rtsock message %ld/%d", length,
(int)sizeof(struct Ipnet_rs_msghdr));
return -1;
}
switch (buf.rtmsg.rtm_type)
{
case IPNET_RTM_DELADDR:
case IPNET_RTM_NEWADDR:
netif = ipmcp_if_find(buf.ifamsg.ifam_index);
if (netif)
{
#ifdef IPMCP_USE_IGMP
ipmcp_igmp_addr_change(netif, buf.rtmsg.rtm_type == IPNET_RTM_NEWADDR);
#endif
#ifdef IPMCP_USE_MLD
ipmcp_mld_addr_change(netif, buf.rtmsg.rtm_type == IPNET_RTM_NEWADDR);
#endif
}
break;
case IPNET_RTM_IFINFO:
if (IP_BIT_ISSET(buf.ifmsg.ifm_flags, IP_IFF_UP))
(void) ipmcp_if_create(buf.ifmsg.ifm_index);
else
ipmcp_if_destroy(ipmcp_if_find(buf.ifmsg.ifm_index));
break;
default:
/* ignore all other routing messages. */
break;
}
return 0;
}
/*
*===========================================================================
* ipmcp_daemon
*===========================================================================
* Description: Multicast proxy daemon.
* Parameters:
* Returns:
*
*/
IPCOM_PROCESS(ipmcp_daemon)
{
int max_fd;
int num;
int ret = 0;
Ip_fd_set read_set;
int retries;
Ip_bool done = IP_FALSE;
ipcom_proc_init();
IPCOM_LOG0(INFO, "Multicast proxy daemon starting");
ret = ipmcp_init();
if (0 > ret)
done = IP_TRUE;
while (!done)
{
ret = ipmcp_setup_configuration();
if (ret != 0)
break;
ipmcp_is_enabled = IP_TRUE;
for (;;)
{
IP_FD_ZERO(&read_set);
IP_FD_SET(ipmcp.ipd_fd, &read_set);
IP_FD_SET(ipmcp.rt_fd, &read_set);
max_fd = IP_MAX(ipmcp.rt_fd, ipmcp.ipd_fd);
#ifdef IPMCP_USE_IGMP
IP_FD_SET(ipmcp.igmp.fd, &read_set);
max_fd = IP_MAX(ipmcp.igmp.fd, max_fd);
#endif
#ifdef IPMCP_USE_MLD
IP_FD_SET(ipmcp.mld.mld_fd, &read_set);
max_fd = IP_MAX(ipmcp.mld.mld_fd, max_fd);
IP_FD_SET(ipmcp.mld.mrt_fd, &read_set);
max_fd = IP_MAX(ipmcp.mld.mrt_fd, max_fd);
#endif
done = IP_TRUE;
for (retries = 0, num = 0; num <= 0 && retries < 3; retries++)
{
num = ipcom_tmo2_select(ipmcp.tmo_head, max_fd + 1, &read_set, IP_NULL, IP_NULL, IP_NULL);
if (num < 0)
IPCOM_LOG1(WARNING, "socket select returned %s", ipcom_strerror(ipcom_errno));
}
if (num < 0)
{
IPCOM_LOG1(ERR, "socket select returned %s, shutting down", ipcom_strerror(ipcom_errno));
break;
}
if (IP_FD_ISSET(ipmcp.ipd_fd, &read_set) && ipmcp_ipd_input(ipmcp.ipd_fd, &done) != 0)
break;
if (IP_FD_ISSET(ipmcp.rt_fd, &read_set) && ipmcp_route_input(ipmcp.rt_fd) < 0)
break;
#ifdef IPMCP_USE_IGMP
if (IP_FD_ISSET(ipmcp.igmp.fd, &read_set)
&& ipmcp_igmp_input(ipmcp.igmp.fd) < 0)
break;
#endif
#ifdef IPMCP_USE_MLD
if (IP_FD_ISSET(ipmcp.mld.mld_fd, &read_set)
&& ipmcp_mld_input(ipmcp.mld.mld_fd) < 0)
break;
if (IP_FD_ISSET(ipmcp.mld.mrt_fd, &read_set)
&& ipmcp_mld_mroute_input(ipmcp.mld.mrt_fd) < 0)
break;
#endif
done = IP_FALSE;
}
ipmcp_teardown_configuration();
}
ipmcp_exit();
IPCOM_LOG0(INFO, "Multicast proxy daemon ending");
ipcom_proc_exit();
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmcp_if_find
*===========================================================================
* Description: Finds the interface that matches the index.
* Parameters:
* Returns: The interface structure or IP_NULL if it does not exists.
*
*/
IP_GLOBAL Ipmcp_netif_t *
ipmcp_if_find(Ip_u32 ifindex)
{
Ipmcp_netif_t *i;
for (i = IPCOM_LIST_FIRST(&ipmcp.downstream_ifs_head);
i != IP_NULL;
i = IPCOM_LIST_NEXT(&i->list))
{
if (ifindex == i->ifindex)
return i;
}
return IP_NULL;
}
/*
*===========================================================================
* ipmcp_route_init_addrs
*===========================================================================
* Description: Sets the address pointer to point to the correct entry
* in the 'rt' buffer.
* Parameters: msg - The first socket address in the route socket message.
* addrs - The IPNET_RTA_xxx from the message.
* sas - Will contain the route pointer.
* Returns:
*
*/
IP_GLOBAL void
ipmcp_route_init_addrs(void *msg, Ip_u32 addrs, struct Ip_sockaddr **sas)
{
int i;
Ip_size_t offset = 0;
for (i = 0; i < IPNET_RTAX_MAX; i++)
{
if (IP_BIT_ISSET(addrs, 1 << i))
{
sas[i] = (struct Ip_sockaddr *) &((Ip_u8 *) msg)[offset];
offset += IPCOM_SA_LEN_GET(sas[i]);
}
else
sas[i] = IP_NULL;
}
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmcp_create
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipmcp_create(void)
{
Ip_err ret;
ipcom_memset(&ipmcp, 0, sizeof(Ipmcp_data_t));
if ((ret = ipcom_mutex_create(&ipmcp.daemon_mutex)) != IPCOM_SUCCESS)
return ret;
if ((ret = ipcom_sem_create(&ipmcp.cmd_sem, 0)) != IPCOM_SUCCESS)
return ret;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipmcp_start
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipmcp_start(void)
{
Ip_err ret;
Ipcom_proc_attr attr;
ipcom_proc_attr_init(&attr);
ipmcp.ipd_fd = IP_INVALID_SOCKET;
ipmcp.rt_fd = IP_INVALID_SOCKET;
#ifdef IPMCP_USE_IGMP
ipmcp.igmp.fd = IP_INVALID_SOCKET;
#endif
#ifdef IPMCP_USE_MLD
ipmcp.mld.mld_fd = IP_INVALID_SOCKET;
ipmcp.mld.mrt_fd = IP_INVALID_SOCKET;
#endif
ret = ipcom_proc_acreate("ipmcp", ipmcp_daemon, &attr, IP_NULL);
ip_assert(ret == IPCOM_SUCCESS);
return ret;
}
/*
*===========================================================================
* ipmcp_version
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC const char *
ipmcp_version(void)
{
return "@(#) IPMCP $Name: VXWORKS_ITER40_2019102207 $ - INTERPEAK_COPYRIGHT_STRING";
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,675 @@
/*
******************************************************************************
* 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
****************************************************************************
*/
+282
View File
@@ -0,0 +1,282 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmcp_h.h,v $ $Revision: 1.18.10.2 $
* $Source: /home/interpeak/CVSRoot/ipmcp/src/ipmcp_h.h,v $
* $Author: svc-cmnet $ $Date: 2013-03-13 07:45:29 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPMCP_H_H
#define IPMCP_H_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmcp_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include <ipcom_hash.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_tmo2.h>
#include <ipcom_type.h>
#ifdef IPMCP_USE_IGMP
#include "ipmcp_igmp.h"
#endif
#ifdef IPMCP_USE_MLD
#include "ipmcp_mld.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* IPD name */
#define IPMCP_IPD_NAME "ipmcp"
/* Tell the daemon to sleep until the shell command has finished */
#define IPMCP_IPD_EVENT_WAIT_FOR_SHELL_CMD 100
/* Syslog */
#define IPCOM_SYSLOG_PRIORITY IPMCP_SYSLOG_PRIORITY
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMCP
/* Multicast proxy daeomon states */
#define IPMCP_STATE_HALTED (0) /* daemon halted */
#define IPMCP_STATE_RUNNING (1) /* daemon running*/
#define IPMCP_STATE_WAITING (2) /* waiting for the uplink to become avaiable */
/* Per-link state */
#define IPMCP_LINK_STATE_INACTIVE (0) /* not acting as IGMP/MLD router on this link */
#define IPMCP_LINK_STATE_NON_QUERIER (1) /* acting as a non-querier */
#define IPMCP_LINK_STATE_QUERIER (2) /* acting as a querier */
/* Link local IP source address availabillity */
#define IPMCP_LINK_LOCAL_ADR_NOTAVAIL (-1) /* no link local address available */
#define IPMCP_LINK_LOCAL_ADR_AVAIL (0) /* link local address is available on this link */
#define IPMCP_LINK_LOCAL_ADR_TENTATIVE (1) /* link local address available, but tentative */
/* Multicast address state */
#define IPMCP_MADDR_STATE_ACTIVE (0) /* Multicast address has listeners */
#define IPMCP_MADDR_STATE_LAST_LISTENER (1) /* Multicast address in last listener state */
/* Address string length for domain unspecific code */
#ifdef IPMCP_USE_MLD
#define IPMCP_ADDRSTRLEN IP_INET6_ADDRSTRLEN
#else
#define IPMCP_ADDRSTRLEN IP_INET_ADDRSTRLEN
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipmcp_netif_t
*===========================================================================
* Generic interface data for downstream interface.
*/
typedef struct Ipmcp_netif_struct
{
Ipcom_list list;
Ip_u32 ifindex;
char ifname[IP_IFNAMSIZ];
#ifdef IPMCP_USE_IGMP
Ipmcp_igmp_netif_t igmp;
#endif
#ifdef IPMCP_USE_MLD
Ipmcp_mld_netif_t mld;
#endif
}
Ipmcp_netif_t;
/*
*===========================================================================
* Ipmcp_upstream_netif_t
*===========================================================================
* Upstream interface.
*/
typedef struct Ipmcp_upstream_netif_struct
{
Ip_u32 ifindex;
char ifname[IP_IFNAMSIZ];
#ifdef IPMCP_USE_IGMP
Ipmcp_igmp_upstream_netif_t igmp;
#endif
#ifdef IPMCP_USE_MLD
Ipmcp_mld_upstream_netif_t mld;
#endif
}
Ipmcp_upstream_netif_t;
/*
*===========================================================================
* Ipmcp_conf
*===========================================================================
* Cached configuration values.
*/
typedef struct Ipmcp_conf_struct
{
/* Number of resends of membership queries, should be higher for link
with high loss probability */
Ip_u32 robustness_variable;
/* Time, in milliseconds, between membership query requests beeing sent */
Ip_u32 query_interval;
/* Maximum time, in milliseconds, before the host must answer on a
membership query */
Ip_u16 query_response_interval;
/* The Startup Query Interval is the interval between General Queries
sent by a Querier on startup */
Ip_u32 startup_query_interval;
/* The Startup Query Count is the number of Queries sent out on startup,
separated by the Startup Query Interval.*/
Ip_u32 startup_query_count;
/* The Last Member Query Interval is the Max Response Time used to
calculate the Max Resp Code inserted into Group-Specific Queries sent
in response to Leave Group messages. It is also the Max Response
Time used in calculating the Max Resp Code for Group-and-Source-
Specific Query messages. Default: query_interval / 4 msec */
Ip_u32 last_member_query_interval;
/* The Last Member Query Count is the number of Group-Specific Queries
sent before the router assumes there are no local members. The Last
Member Query Count is also the number of Group-and-Source-Specific
Queries sent before the router assumes there are no listeners for a
particular source. Default: the Robustness Variable.*/
Ip_u32 last_member_query_count;
char *downstream_ifs;
} Ipmcp_conf_t;
/*
*===========================================================================
* Ipmlds_data_t
*===========================================================================
* IPMCP global data.
*/
typedef struct Ipmcp_data_struct
{
Ipcom_sem cmd_sem;
Ipcom_mutex daemon_mutex;
/* One of the IPMCP_STATE_xxx states */
int state;
/* IPD socket */
Ip_fd ipd_fd;
/* Route message socket */
Ip_fd rt_fd;
#ifdef IP_PORT_LAS
/* Config socket */
Ip_fd cfg_fd;
#endif
/* Timeout queue */
Ipcom_pqueue *tmo_head;
/* Upstream interface, this is the only interface that IPv6 multicast
traffic can be forwared from */
Ipmcp_upstream_netif_t upstream_if;
/* interface list */
Ipcom_list downstream_ifs_head;
/* cached configuration variables */
Ipmcp_conf_t config;
#ifdef IPMCP_USE_IGMP
Ipmcp_igmp_data_t igmp;
#endif
#ifdef IPMCP_USE_MLD
Ipmcp_mld_data_t mld;
#endif
Ip_u32 send_buf[1500 / sizeof(Ip_u32)];
Ip_u32 recv_buf[1500/ sizeof(Ip_u32)];
char log_buf[100];
} Ipmcp_data_t;
IP_EXTERN Ipmcp_data_t ipmcp;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipmcp_netif_t * ipmcp_if_find(Ip_u32 ifindex);
IP_GLOBAL void ipmcp_route_init_addrs(void *msg, Ip_u32 addrs, struct Ip_sockaddr **sas);
#ifdef IPMCP_USE_IGMP
IP_GLOBAL int ipmcp_igmp_init(void);
IP_GLOBAL void ipmcp_igmp_exit(void);
IP_GLOBAL int ipmcp_igmp_if_create(Ipmcp_netif_t *netif);
IP_GLOBAL void ipmcp_igmp_if_destroy(Ipmcp_netif_t *netif);
IP_GLOBAL int ipmcp_igmp_upstream_if_create(Ipmcp_upstream_netif_t *netif);
IP_GLOBAL void ipmcp_igmp_upstream_if_destroy(Ipmcp_upstream_netif_t *netif);
IP_GLOBAL void ipmcp_igmp_addr_change(Ipmcp_netif_t *netif, Ip_bool add);
IP_GLOBAL int ipmcp_igmp_input(int fd);
#endif /* IPMCP_USE_IGMP */
#ifdef IPMCP_USE_MLD
IP_GLOBAL int ipmcp_mld_init(void);
IP_GLOBAL void ipmcp_mld_exit(void);
IP_GLOBAL int ipmcp_mld_if_create(Ipmcp_netif_t *netif);
IP_GLOBAL void ipmcp_mld_if_destroy(Ipmcp_netif_t *netif);
IP_GLOBAL int ipmcp_mld_upstream_if_create(Ipmcp_upstream_netif_t *netif);
IP_GLOBAL void ipmcp_mld_upstream_if_destroy(Ipmcp_upstream_netif_t *netif);
IP_GLOBAL void ipmcp_mld_addr_change(Ipmcp_netif_t *netif, Ip_bool add);
IP_GLOBAL int ipmcp_mld_input(int fd);
IP_GLOBAL int ipmcp_mld_mroute_input(int fd);
IP_GLOBAL void ipmcp_mld_show_joined_groups_cb(void *obj, void *unused);
#endif /* IPMCP_USE_MLD */
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,192 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmcp_igmp.h,v $ $Revision: 1.10 $
* $Source: /home/interpeak/CVSRoot/ipmcp/src/ipmcp_igmp.h,v $
* $Author: kenneth $ $Date: 2010-12-17 08:56:00 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPMCP_IGMP_H
#define IPMCP_IGMP_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmcp_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include <ipcom_type.h>
#include "ipmcp_mcast.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipmcp_igmp_maddr_struct
*===========================================================================
* IPv4 multicast address descriptor for a downstream interface.
* This structure represents a multicast address that has listener on its
* link.
*/
typedef struct Ipmcp_igmp_maddr_struct
{
Ipmcp_maddr_t base; /* Base class */
struct Ip_in_addr maddr;
/* Less than max-response-interval has passed since a specific query was sent */
Ipcom_tmo2 specific_query_pending_timer;
Ipcom_tmo2 v1_host_present_timer; /* In IGMPv1 compatibility mode if this is running */
Ipcom_tmo2 v2_host_present_timer; /* In IGMPv2 compatibility mode if this is running */
} Ipmcp_igmp_maddr_t;
/*
*===========================================================================
* Ipmcp_igmp_upstream_maddr
*===========================================================================
* IPv4 multicast address descriptor for the upstream link.
* This structure represents all multicast/source address pairs from which
* there is:
* - at least one listener on one (or more) of the downstream links
* - at least one packet has been received directed to this multicast address
* from a sourec now included in the 'saddrs' list.
*/
typedef struct Ipmcp_igmp_upstream_maddr_struct
{
Ipmcp_upstream_maddr_t base; /* Base class */
struct Ip_in_addr maddr;
int next_src_addr;
/* Sources from downstream and upstream networks are stored in this array */
struct Ip_in_addr saddrs[IPMCP_IGMP_MAX_SRC_ADDRS];
}
Ipmcp_igmp_upstream_maddr_t;
/*
*===========================================================================
* Ipmcp_igmp_netif_t
*===========================================================================
* Downstream IPv4 interface data, the proxy acts as an IGMP router on this
* interface.
*/
typedef struct Ipmcp_igmp_netif_struct
{
Ip_bool need_if_create;
/* One of the IPMCP_LINK_STATE_xxx flags */
Ip_u16 state;
Ip_u16 robustness_variable;
/* Number of queries to send using the Startup Query Interval */
Ip_u16 startup_query_count;
/* Query interval for this link, in milliseconds */
Ip_u32 query_interval;
/* Timer for the next query if in querier state,
timer when to resume as querier if in non-querier state */
Ipcom_tmo2 timer;
/* Virtual interface index that maps to this physical interface */
Ip_vifi_t vif_index;
/* The primary IPv4 address for this interface */
struct Ip_in_addr primary_address;
/* IPv4 multicast address database */
Ipcom_hash *maddr_head;
}
Ipmcp_igmp_netif_t;
/*
*===========================================================================
* Ipmcp_igmp_upstream_netif_t
*===========================================================================
* Upstream IPv4 interface data.
*/
typedef struct Ipmcp_igmp_upstream_netif_struct
{
/* The primary IPv4 address for this interface */
struct Ip_in_addr primary_address;
/* Virtual interface index that maps to this physical interface */
Ip_vifi_t vif_index;
/* IPv4 multicast address database */
Ipcom_hash *maddr_head;
}
Ipmcp_igmp_upstream_netif_t;
/*
*===========================================================================
* Ipmcp_igmp_data_t
*===========================================================================
* Multicast proxy IGMP global data.
*/
typedef struct Ipmcp_igmp_data_struct
{
/* Socket used to listen/send IGMP messages on and
Multicast forward cache control socket */
Ip_fd fd;
/* The 224.0.0.1 multicast address */
struct Ip_in_addr all_hosts_addr;
/* Index of last virtual interface created */
Ip_vifi_t last_vifi;
/* Method table for Ipmcp_igmp_rec_t class */
Ipmcp_rec_ops_t rec_ops;
/* Method table for Ipmcp_igmp_saddr_t class */
Ipmcp_saddr_ops_t saddr_ops;
/* Method table for Ipmcp_igmp_maddr_t class */
Ipmcp_maddr_ops_t maddr_ops;
/* Method table for Ipmcp_igmp_uplink_maddr_t class */
Ipmcp_upstream_maddr_ops_t upstream_maddr_ops;
} Ipmcp_igmp_data_t;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,262 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmcp_mcast.h,v $ $Revision: 1.3 $
* $Source: /home/interpeak/CVSRoot/ipmcp/src/ipmcp_mcast.h,v $
* $Author: kenneth $ $Date: 2010-12-17 15:39:19 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPMCP_MCAST_H
#define IPMCP_MCAST_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* Generic functions that can operate on both IPv4 and IPv6 addresses.
* Implements most of the processing described in RFC3376 and RFC3810
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmcp_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include <ipcom_hash.h>
#include <ipcom_set.h>
#include <ipcom_type.h>
#include <ipcom_tmo2.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* IGMPv3 and MLDv2 Group record types */
#define IPMCP_GROUP_REC_TYPE_MODE_IS_INCLUDE 1
#define IPMCP_GROUP_REC_TYPE_MODE_IS_EXCLUDE 2
#define IPMCP_GROUP_REC_TYPE_MODE_CHANGE_TO_INCLUDE_MODE 3
#define IPMCP_GROUP_REC_TYPE_MODE_CHANGE_TO_EXCLUDE_MODE 4
#define IPMCP_GROUP_REC_TYPE_MODE_ALLOW_NEW_SOURCES 5
#define IPMCP_GROUP_REC_TYPE_MODE_BLOCK_OLD_SOURCES 6
/* Group compatibility modes */
#define IPMCP_MCAST_COMPAT_IGMPV1 1
#define IPMCP_MCAST_COMPAT_IGMPV2_MLDV1 2
#define IPMCP_MCAST_COMPAT_IGMPV3_MLDV2 3
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipmcp_rec_t
*===========================================================================
* Base class for IGMPv3 and MLDv2 membership report record
*/
struct Ipmcp_rec_struct;
#define RTHIS struct Ipmcp_rec_struct *self
typedef struct Ipmcp_rec_ops_struct
{
/* Returns the record type */
Ip_u8 (*get_type)(RTHIS);
/* Returns a pointer to the group address */
void * (*get_maddr)(RTHIS);
/* Returns the number of source addresses */
unsigned (*get_num_saddrs)(RTHIS);
/* Returns a pointer to the source address with index 'i' */
void * (*get_saddr)(RTHIS, unsigned i);
/* Returns a IPCOM set with all source address in this record */
Ipcom_set * (*as_set)(RTHIS);
/* Removes all source addresses from the record */
void (*clear_source_list)(RTHIS);
} Ipmcp_rec_ops_t;
typedef struct Ipmcp_rec_struct
{
Ipmcp_rec_ops_t *ops;
} Ipmcp_rec_t;
/*
*===========================================================================
* Ipmcp_saddr_t
*===========================================================================
* Base class a multicast source address entry
*/
struct Ipmcp_saddr_struct;
#define STHIS struct Ipmcp_saddr_struct *self
typedef struct Ipmcp_saddr_ops_struct
{
void (*dtor)(STHIS);
void (*set_timer)(STHIS, Ip_u32 msec);
void * (*get_addr)(STHIS);
} Ipmcp_saddr_ops_t;
typedef struct Ipmcp_saddr_struct
{
Ipmcp_saddr_ops_t *ops;
Ipcom_tmo2 timer; /* Source timer, entry is remove when this expires */
struct Ipmcp_maddr_struct *maddr; /* The multicast address this entry is part of */
} Ipmcp_saddr_t;
/*
*===========================================================================
* Ipmcp_maddr_t
*===========================================================================
* Base class a multicast address entry
*/
struct Ipmcp_maddr_struct;
#define MTHIS struct Ipmcp_maddr_struct *self
typedef struct Ipmcp_maddr_ops_struct
{
void (*dtor)(MTHIS);
void * (*get_addr)(MTHIS);
int (*compatibility_mode)(MTHIS);
Ipmcp_saddr_t * (*add_saddr)(MTHIS, IP_CONST void *saddr, Ip_bool is_include_set);
Ipmcp_saddr_t * (*get_saddr)(MTHIS, IP_CONST void *saddr, Ip_bool is_include_set);
void (*del_saddrs_not_in_rec)(MTHIS, Ipmcp_rec_t *rec, Ip_bool is_include_set);
void (*send_query)(MTHIS, Ip_u32 max_response_msec, Ipcom_set *saddr_set);
Ip_u32 (*get_group_timer) (MTHIS);
void (*set_group_timer)(MTHIS, Ip_u32 msec);
Ip_u32 (*group_membership_interval)(MTHIS);
void (*update_upstream_if_filter)(MTHIS);
} Ipmcp_maddr_ops_t;
typedef struct Ipmcp_maddr_struct
{
Ipmcp_maddr_ops_t *ops;
int domain;
unsigned addr_len; /* Address length for this domain */
Ipcom_tmo2 group_timer; /* Will switch to INCLUDE mode when this expires */
/* Fields use in specific queries on this group */
unsigned query_count; /* Number of times the current specific query will be resent */
Ipcom_tmo2 query_timer; /* Will send a specific query when expires */
Ip_u8 query_suppress_router_side_processing; /* Set to IP_TRUE if the S bit should be set in
the next specific query for this address */
/* Fields use in source specific queries on this group */
Ip_u8 source_query_suppress_router_side_processing; /* Set to IP_TRUE if the S bit should be set in
the next source specific query for this address */
unsigned source_query_count; /* Number of times the current specific query will be resent */
Ipcom_tmo2 source_query_timer; /* Will send a specific query when expires */
Ipcom_set *report_set; /* Set of sources to include in the next source specific query */
/* Multicast source addresses sets */
Ip_bool mode_is_include;
Ipcom_hash *include_set; /* Set of sources that at least one listener want */
Ipcom_hash *exclude_set; /* Set of sources that at least one listener do not want */
/* Downstream interface for which this entry is valid */
struct Ipmcp_netif_struct *netif;
} Ipmcp_maddr_t;
/*
*===========================================================================
* Ipmcp_upstream_maddr_t
*===========================================================================
* Base class a multicast address entry
*/
struct Ipmcp_upstream_maddr_struct;
#define UTHIS struct Ipmcp_upstream_maddr_struct *self
typedef struct Ipmcp_upstream_maddr_ops_struct
{
void (*dtor)(UTHIS);
void * (*get_addr)(UTHIS);
void (*change_mode)(UTHIS, Ip_bool to_exclude);
void (*add_source)(UTHIS, void *saddr);
void (*del_source)(UTHIS, void *saddr);
} Ipmcp_upstream_maddr_ops_t;
typedef struct Ipmcp_upstream_maddr_struct
{
Ipmcp_upstream_maddr_ops_t *ops; /* Upstream operations */
Ipcom_set *filter; /* Current source filter */
} Ipmcp_upstream_maddr_t;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL int
ipmcp_handle_membership_report_rec(Ipmcp_maddr_t *maddr_obj, Ipmcp_rec_t *rec_obj);
IP_GLOBAL Ip_u32
ipmcp_last_member_query_time(void);
IP_GLOBAL void
ipmcp_update_upstream_if_filter(Ipmcp_upstream_maddr_t *maddr_obj,
Ipcom_hash*(*get_maddr_head)(struct Ipmcp_netif_struct *));
IP_GLOBAL Ip_u32
ipmcp_qqic_to_msec(Ip_u8 code);
IP_GLOBAL Ip_u8
ipmcp_qqic_from_msec(Ip_u32 msec, int version);
/* Source address methods */
IP_GLOBAL void
ipmcp_saddr_ops_init(Ipmcp_saddr_ops_t *ops);
/* Multicast address methods */
IP_GLOBAL void
ipmcp_maddr_drop(Ipmcp_maddr_t *maddr, void *unused);
IP_GLOBAL void
ipmcp_maddr_cleanup(Ipmcp_maddr_t *maddr);
IP_GLOBAL void
ipmcp_maddr_ops_init(Ipmcp_maddr_ops_t *ops);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,187 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmcp_mld.h,v $ $Revision: 1.8 $
* $Source: /home/interpeak/CVSRoot/ipmcp/src/ipmcp_mld.h,v $
* $Author: kenneth $ $Date: 2010-12-17 08:56:05 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPMCP_MLD_H
#define IPMCP_MLD_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmcp_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include <ipcom_type.h>
#include "ipmcp_mcast.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipmcp_mld_netif_t
*===========================================================================
* Downstream IPv6 interface data.
*/
typedef struct Ipmcp_mld_netif_struct
{
/* One of the IPMCP_LINK_STATE_xxx flags */
int no_rt_count;
Ip_u16 state;
Ip_u16 robustness_variable;
Ip_u16 startup_query_count;
/* Query interval for this link, in milliseconds */
Ip_u32 query_interval;
/* Timer for the next query if in querier state,
timer when to resume as querier if in non-querier state */
Ipcom_tmo2 timer;
/* Multicast interface index that maps to this physical interface */
Ip_mifi_t mif_index;
/* The link local IPv6 address for this interface */
struct Ip_in6_addr link_local_address;
/* IPv6 multicast address database */
Ipcom_hash *maddr_head;
}
Ipmcp_mld_netif_t;
/*
*===========================================================================
* Ipmcp_mld_netif_t
*===========================================================================
* Upstream IPv6 interface data.
*/
typedef struct Ipmcp_mld_upstream_netif_struct
{
/* The link local IPv6 address for this interface */
struct Ip_in6_addr link_local_address;
/* Multicast interface index that maps to this physical interface */
Ip_mifi_t mif_index;
/* IPv6 multicast address database */
Ipcom_hash *maddr_head;
}
Ipmcp_mld_upstream_netif_t;
/*
*===========================================================================
* Ipmcp_mld_maddr_t
*===========================================================================
* MLD multicast address descriptor
*/
typedef struct Ipmcp_mld_maddr_struct
{
Ipmcp_maddr_t base; /* Base class */
struct Ip_in6_addr maddr;
/* Less than max-response-interval has passed since a specific query was sent */
Ipcom_tmo2 specific_query_pending_timer;
Ipcom_tmo2 v1_host_present_timer; /* In MLDv1 compatibility mode if this is running */
} Ipmcp_mld_maddr_t;
/*
*===========================================================================
* Ipmcp_mld_upstream_maddr
*===========================================================================
* IPv6 multicast address descriptor for the upstream link.
* This structure represents all multicast/source address pairs from which
* there is:
* - at least one listener on one (or more) of the downstream links
* - at least one packet has been received directed to this multicast address
* from a sourec now included in the 'saddrs' list.
*/
typedef struct Ipmcp_mld_upstream_maddr_struct
{
Ipmcp_upstream_maddr_t base; /* Base class */
struct Ip_in6_addr maddr;
int next_src_addr;
/* Sources from downstream and upstream networks are stored in this array */
struct Ip_in6_addr saddrs[IPMCP_MLD_MAX_SRC_ADDRS];
}
Ipmcp_mld_upstream_maddr_t;
/*
*===========================================================================
* Ipmcp_mld_data_t
*===========================================================================
* Multicast proxy MLD global data.
*/
typedef struct Ipmcp_mld_data_struct
{
/* Socket used to listen/send MLD messages on */
Ip_fd mld_fd;
/* Multicast forward cache control socket */
Ip_fd mrt_fd;
/* The ff02::1 multicast address */
struct Ip_in6_addr all_hosts_addr;
/* Index of last multicast interface created */
Ip_mifi_t last_mifi;
/* Method table for Ipmcp_mld_rec_t class */
Ipmcp_rec_ops_t rec_ops;
/* Method table for Ipmcp_mld_saddr_t class */
Ipmcp_saddr_ops_t saddr_ops;
/* Method table for Ipmcp_mld_maddr_t class */
Ipmcp_maddr_ops_t maddr_ops;
/* Method table for Ipmcp_mld_uplink_maddr_t class */
Ipmcp_upstream_maddr_ops_t upstream_maddr_ops;
} Ipmcp_mld_data_t;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/