summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: eb08358)
raw | patch | inline | side by side (parent: eb08358)
author | Max Henkel <henkel@gmx.at> | |
Fri, 2 Apr 2010 10:39:19 +0000 (12:39 +0200) | ||
committer | Florian Forster <octo@huhu.verplant.org> | |
Mon, 5 Apr 2010 13:37:21 +0000 (15:37 +0200) |
Hello list!
Again I'm providing an interface option for the network plugin for
the manual selection of an incoming or outgoing interface,
incorporating the changes proposed by Florian and Sebastian.
Please look through it and feedback or suggest new changes! :-)
Best regards,
Max
Signed-off-by: Florian Forster <octo@huhu.verplant.org>
Again I'm providing an interface option for the network plugin for
the manual selection of an incoming or outgoing interface,
incorporating the changes proposed by Florian and Sebastian.
Please look through it and feedback or suggest new changes! :-)
Best regards,
Max
Signed-off-by: Florian Forster <octo@huhu.verplant.org>
src/collectd.conf.pod | patch | blob | history | |
src/network.c | patch | blob | history |
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 9cab554898c2b68d8ada8d5cfdd9c5a242e3dc8d..c490a2e47ffe77170fdba2323d135f15cdfbc534 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -2569,6 +2569,13 @@ multicast, and IPv4 and IPv6 packets. The default is to not change this value.
That means that multicast packets will be sent with a TTL of C<1> (one) on most
operating systems.
+=item B<Interface> I<Interface name>
+
+Set the outgoing or incoming interface for multicast packets. This applies
+at least to IPv6 packets and if possible to IPv4. If it is not applicable or
+defined the default behaviour is to let the kernel choose the appropriate
+interface.
+
=item B<MaxPacketSize> I<1024-65535>
Set the maximum size for datagrams received over the network. Packets larger
diff --git a/src/network.c b/src/network.c
index 8615753807445755cab2b4a49c87b73e9e4ea893..b6e21b999952424780abc4aeb883a739af14fdda 100644 (file)
--- a/src/network.c
+++ b/src/network.c
#if HAVE_POLL_H
# include <poll.h>
#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
#if HAVE_LIBGCRYPT
# include <gcrypt.h>
* Private variables
*/
static int network_config_ttl = 0;
+static int network_config_interface_idx = 0;
static size_t network_config_packet_size = 1024;
static int network_config_forward = 0;
static int network_config_stats = 0;
return (0);
} /* int network_set_ttl */
+static int network_set_interface (const sockent_t *se, const struct addrinfo *ai) /* {{{ */
+{
+ DEBUG ("network plugin: network_set_interface: interface index = %i;",
+ network_config_interface_idx);
+
+ assert (se->type == SOCKENT_TYPE_CLIENT);
+
+ if (ai->ai_family == AF_INET)
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
+#if KERNEL_LINUX
+ struct ip_mreqn mreq;
+#else
+ struct ip_mreq mreq;
+#endif
+
+ if (! IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+ return (0);
+
+ mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+#if KERNEL_LINUX
+ mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+ mreq.imr_ifindex = network_config_interface_idx;
+#else
+ mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
+
+ if (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF,
+ &mreq, sizeof (mreq)) == -1)
+ {
+ char errbuf[1024];
+ ERROR ("setsockopt: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+ }
+ else if (ai->ai_family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
+
+ if (! IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+ return (0);
+
+ if (setsockopt (se->data.client.fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &network_config_interface_idx,
+ sizeof (network_config_interface_idx)) == -1)
+ {
+ char errbuf[1024];
+ ERROR ("setsockopt: %s",
+ sstrerror (errno, errbuf,
+ sizeof (errbuf)));
+ return (-1);
+ }
+ }
+
+ return (0);
+} /* }}} network_set_interface */
+
static int network_bind_socket (int fd, const struct addrinfo *ai)
{
int loop = 0;
struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
{
+#if KERNEL_LINUX
+ struct ip_mreqn mreq;
+#else
struct ip_mreq mreq;
+#endif
DEBUG ("fd = %i; IPv4 multicast address found", fd);
mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
- mreq.imr_interface.s_addr = htonl (INADDR_ANY);
+#if KERNEL_LINUX
+ mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+ mreq.imr_ifindex = network_config_interface_idx;
+#else
+ mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
if (setsockopt (fd, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, sizeof (loop)) == -1)
* single interface; programs running on
* multihomed hosts may need to join the same
* group on more than one interface.*/
- mreq.ipv6mr_interface = 0;
+ mreq.ipv6mr_interface = network_config_interface_idx;
if (setsockopt (fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&loop, sizeof (loop)) == -1)
se->data.client.addrlen = ai_ptr->ai_addrlen;
network_set_ttl (se, ai_ptr);
+ network_set_interface (se, ai_ptr);
/* We don't open more than one write-socket per
* node/service pair.. */
return (0);
} /* }}} int network_config_set_ttl */
+static int network_config_set_interface (const oconfig_item_t *ci) /* {{{ */
+{
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("network plugin: The `Interface' config option needs exactly "
+ "one string argument.");
+ return (-1);
+ }
+
+ network_config_interface_idx = if_nametoindex (ci->values[0].value.string);
+
+ return (0);
+} /* }}} int network_config_set_interface */
+
static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
{
int tmp;
network_config_add_server (child);
else if (strcasecmp ("TimeToLive", child->key) == 0)
network_config_set_ttl (child);
+ else if (strcasecmp ("Interface", child->key) == 0)
+ network_config_set_interface (child);
else if (strcasecmp ("MaxPacketSize", child->key) == 0)
network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)