/**
- * collectd - src/libcollectdclient/network.h
- * Copyright (C) 2005-2010 Florian octo Forster
+ * collectd - src/libcollectdclient/network.c
+ * Copyright (C) 2005-2013 Florian Forster
+ * Copyright (C) 2010 Max Henkel
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; only version 2.1 of the License is
- * applicable.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian Forster <octo at collectd.org>
+ * Max Henkel <henkel at gmx.at>
**/
+#include "collectd.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
#include "collectd/network.h"
#include "collectd/network_buffer.h"
return (0);
} /* }}} int lcc_server_set_ttl */
+int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
+{
+ int if_index;
+ int status;
+
+ if ((srv == NULL) || (interface == NULL))
+ return (EINVAL);
+
+ if_index = if_nametoindex (interface);
+ if (if_index == 0)
+ return (ENOENT);
+
+ /* IPv4 multicast */
+ if (srv->sa->sa_family == AF_INET)
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *) srv->sa;
+
+ if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+ {
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+ /* If possible, use the "ip_mreqn" structure which has
+ * an "interface index" member. Using the interface
+ * index is preferred here, because of its similarity
+ * to the way IPv6 handles this. Unfortunately, it
+ * appears not to be portable. */
+ struct ip_mreqn mreq;
+
+ memset (&mreq, 0, sizeof (mreq));
+ mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+ mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+ mreq.imr_ifindex = if_index;
+#else
+ struct ip_mreq mreq;
+
+ memset (&mreq, 0, sizeof (mreq));
+ mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+ mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
+
+ status = setsockopt (srv->fd, IPPROTO_IP, IP_MULTICAST_IF,
+ &mreq, sizeof (mreq));
+ if (status != 0)
+ return (status);
+
+ return (0);
+ }
+ }
+
+ /* IPv6 multicast */
+ if (srv->sa->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) srv->sa;
+
+ if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+ {
+ status = setsockopt (srv->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &if_index, sizeof (if_index));
+ if (status != 0)
+ return (status);
+
+ return (0);
+ }
+ }
+
+ /* else: Not a multicast interface. */
+#if defined(SO_BINDTODEVICE)
+ status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
+ interface, strlen (interface) + 1);
+ if (status != 0)
+ return (-1);
+#endif
+
+ return (0);
+} /* }}} int lcc_server_set_interface */
+
int lcc_server_set_security_level (lcc_server_t *srv, /* {{{ */
lcc_security_level_t level,
const char *username, const char *password)