From 97f25892ea38e227fe802d0cc50fd88be12cdb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 13 Jan 2012 12:37:31 +0100 Subject: [PATCH] GSocket: Add possibility to join a multicast group only on a specific interface --- configure.ac | 4 ++++ gio/gnetworkingprivate.h | 1 + gio/gsocket.c | 28 +++++++++++++++++++++++++--- gio/gsocket.h | 2 ++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index d3628e537..630656bea 100644 --- a/configure.ac +++ b/configure.ac @@ -1109,6 +1109,10 @@ AC_CHECK_HEADER([linux/netlink.h], [#include ]) AM_CONDITIONAL(HAVE_NETLINK, [test "$ac_cv_header_linux_netlink_h" = "yes"]) +AC_CHECK_TYPE([struct ip_mreqn], [ + AC_DEFINE(HAVE_IP_MREQN,, [Define if we have struct ip_mreqn])],, + [#include ]) + case $host in *-*-solaris* ) AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, Needed to get declarations for msg_control and msg_controllen on Solaris) diff --git a/gio/gnetworkingprivate.h b/gio/gnetworkingprivate.h index 5ca7c17e1..ce31b1e5e 100644 --- a/gio/gnetworkingprivate.h +++ b/gio/gnetworkingprivate.h @@ -53,6 +53,7 @@ #if defined(HAVE_ARPA_NAMESER_COMPAT_H) && !defined(GETSHORT) #include #endif +#include #ifndef T_SRV #define T_SRV 33 diff --git a/gio/gsocket.c b/gio/gsocket.c index 416ac77db..e2e4e3974 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -47,6 +47,8 @@ #include #endif +#include + #include "gcancellable.h" #include "gioenumtypes.h" #include "ginetaddress.h" @@ -1688,6 +1690,7 @@ g_socket_bind (GSocket *socket, static gboolean g_socket_multicast_group_operation (GSocket *socket, GInetAddress *group, + const gchar *interface, gboolean join_group, GError **error) { @@ -1705,10 +1708,22 @@ g_socket_multicast_group_operation (GSocket *socket, native_addr = g_inet_address_to_bytes (group); if (socket->priv->family == G_SOCKET_FAMILY_IPV4) { +#ifdef HAVE_IP_MREQN + struct ip_mreqn mc_req; +#else struct ip_mreq mc_req; +#endif memcpy (&mc_req.imr_multiaddr, native_addr, sizeof (struct in_addr)); + +#ifdef HAVE_IP_MREQN + if (interface) + mc_req.imr_ifindex = if_nametoindex (interface); + else + mc_req.imr_ifindex = 0; /* Pick any. */ +#else mc_req.imr_interface.s_addr = g_htonl (INADDR_ANY); +#endif optname = join_group ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; result = setsockopt (socket->priv->fd, IPPROTO_IP, optname, @@ -1719,7 +1734,10 @@ g_socket_multicast_group_operation (GSocket *socket, struct ipv6_mreq mc_req_ipv6; memcpy (&mc_req_ipv6.ipv6mr_multiaddr, native_addr, sizeof (struct in6_addr)); - mc_req_ipv6.ipv6mr_interface = 0; + if (interface) + mc_req_ipv6.ipv6mr_interface = if_nametoindex (interface); + else + mc_req_ipv6.ipv6mr_interface = 0; optname = join_group ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP; result = setsockopt (socket->priv->fd, IPPROTO_IPV6, optname, @@ -1747,6 +1765,7 @@ g_socket_multicast_group_operation (GSocket *socket, * g_socket_join_multicast_group: * @socket: a #GSocket. * @group: a #GInetAddress specifying the group address to join. + * @interface: Interface to use * @error: #GError for error reporting, or %NULL to ignore. * * Registers @socket to receive multicast messages sent to @group. @@ -1761,15 +1780,17 @@ g_socket_multicast_group_operation (GSocket *socket, gboolean g_socket_join_multicast_group (GSocket *socket, GInetAddress *group, + const gchar *interface, GError **error) { - return g_socket_multicast_group_operation (socket, group, TRUE, error); + return g_socket_multicast_group_operation (socket, group, interface, TRUE, error); } /** * g_socket_leave_multicast_group: * @socket: a #GSocket. * @group: a #GInetAddress specifying the group address to leave. + * @interface: Interface to use * @error: #GError for error reporting, or %NULL to ignore. * * Removes @socket from the multicast group @group (while still @@ -1782,9 +1803,10 @@ g_socket_join_multicast_group (GSocket *socket, gboolean g_socket_leave_multicast_group (GSocket *socket, GInetAddress *group, + const gchar *interface, GError **error) { - return g_socket_multicast_group_operation (socket, group, FALSE, error); + return g_socket_multicast_group_operation (socket, group, interface, FALSE, error); } /** diff --git a/gio/gsocket.h b/gio/gsocket.h index d83387515..5cfec2ffa 100644 --- a/gio/gsocket.h +++ b/gio/gsocket.h @@ -113,9 +113,11 @@ gboolean g_socket_bind (GSocket GError **error); gboolean g_socket_join_multicast_group (GSocket *socket, GInetAddress *group, + const gchar *interface, GError **error); gboolean g_socket_leave_multicast_group (GSocket *socket, GInetAddress *group, + const gchar *interface, GError **error); gboolean g_socket_connect (GSocket *socket, GSocketAddress *address,