/**
- * collectd - src/libcollectdclient/network.h
- * Copyright (C) 2005-2010 Florian octo Forster
+ * collectd - src/libcollectdclient/network.c
+ * Copyright (C) 2005-2015 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);
close (srv->fd);
+ srv->fd = -1;
free (srv->sa);
srv->sa = NULL;
srv->sa_len = 0;
next = srv->next;
- if (srv->fd >= 0)
- {
- close (srv->fd);
- srv->fd = -1;
- }
-
free (srv->node);
free (srv->service);
free (srv->username);
memset (buffer, 0, sizeof (buffer));
buffer_size = sizeof (buffer);
- lcc_network_buffer_finalize (srv->buffer);
+ status = lcc_network_buffer_finalize (srv->buffer);
+ if (status != 0)
+ {
+ lcc_network_buffer_initialize (srv->buffer);
+ return (status);
+ }
+
status = lcc_network_buffer_get (srv->buffer, buffer, &buffer_size);
lcc_network_buffer_initialize (srv->buffer);
return (0);
} /* }}} int lcc_server_set_ttl */
-int lcc_server_set_security_level (lcc_server_t *srv, /* {{{ */
- lcc_security_level_t level)
+int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
{
- if ((srv == NULL)
- || ((level != NONE) && (level != SIGN) && (level != ENCRYPT)))
+ unsigned int if_index;
+ int status;
+
+ if ((srv == NULL) || (interface == NULL))
return (EINVAL);
- srv->security_level = level;
+ if_index = if_nametoindex (interface);
+ if (if_index == 0)
+ return (ENOENT);
- return (0);
-} /* }}} int lcc_server_set_security_level */
+ /* IPv4 multicast */
+ if (srv->sa->sa_family == AF_INET)
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *) srv->sa;
-int lcc_server_set_credentials (lcc_server_t *srv, /* {{{ */
- const char *username, const char *password)
-{
- char *tmp_username;
- char *tmp_password;
+ 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 = (int) 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
- if ((srv == NULL) || (username == NULL) || (password == NULL))
- return (EINVAL);
+ status = setsockopt (srv->fd, IPPROTO_IP, IP_MULTICAST_IF,
+ &mreq, sizeof (mreq));
+ if (status != 0)
+ return (status);
- tmp_username = strdup (username);
- if (tmp_username == NULL)
- return (ENOMEM);
+ return (0);
+ }
+ }
- tmp_password = strdup (password);
- if (tmp_password == NULL)
+ /* IPv6 multicast */
+ if (srv->sa->sa_family == AF_INET6)
{
- free (tmp_username);
- return (ENOMEM);
- }
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) srv->sa;
- free (srv->username);
- free (srv->password);
+ 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);
- srv->username = tmp_username;
- srv->password = tmp_password;
+ return (0);
+ }
+ }
+
+ /* else: Not a multicast interface. */
+#if defined(SO_BINDTODEVICE)
+ status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE, interface,
+ (socklen_t) (strlen (interface) + 1));
+ if (status != 0)
+ return (-1);
+#endif
return (0);
-} /* }}} int lcc_server_set_credentials */
+} /* }}} 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)
+{
+ return (lcc_network_buffer_set_security_level (srv->buffer,
+ level, username, password));
+} /* }}} int lcc_server_set_security_level */
int lcc_network_values_send (lcc_network_t *net, /* {{{ */
const lcc_value_list_t *vl)