Code

Deleted `multicast.c' and `multicast.h'
[collectd.git] / src / network.c
index f42693e1c494f90359b1877c4148c8e4a5fef45e..ddc36e772176aa57715471ff652ebb7c5229d82a 100644 (file)
 
 #include "network.h"
 #include "common.h"
-
-/*
- * From RFC2365:
- *
- * The IPv4 Organization Local Scope -- 239.192.0.0/14
- *
- * 239.192.0.0/14 is defined to be the IPv4 Organization Local Scope, and is
- * the space from which an organization should allocate sub-ranges when
- * defining scopes for private use.
- *
- * Port 25826 is not assigned as of 2005-09-12
- */
-
-#define IPV4_MCAST_GROUP "239.192.74.66"
-#define UDP_PORT 25826
+#include "utils_debug.h"
 
 /* 1500 - 40 - 8  =  Ethernet packet - IPv6 header - UDP header */
-#define BUFF_SIZE 1452
+/* #define BUFF_SIZE 1452 */
 
 #define BUFF_SIZE 4096
 
@@ -64,6 +50,7 @@ static int operating_mode = MODE_CLIENT;
 typedef struct sockent
 {
        int                      fd;
+       int                      mode;
        struct sockaddr_storage *addr;
        socklen_t                addrlen;
        struct sockent          *next;
@@ -71,11 +58,13 @@ typedef struct sockent
 
 static sockent_t *socklist_head = NULL;
 
-static int network_bind_socket (int fd, const struct addrinfo *ai, const sockent_t *se)
+static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
 {
        int loop = 1;
 
-       if (bind (fd, ai->ai_addr, ai->ai_addrlen) == -1)
+       DBG ("fd = %i; calling `bind'", se->fd);
+
+       if (bind (se->fd, ai->ai_addr, ai->ai_addrlen) == -1)
        {
                syslog (LOG_ERR, "bind: %s", strerror (errno));
                return (-1);
@@ -88,6 +77,8 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const sockent
                {
                        struct ip_mreq mreq;
 
+                       DBG ("fd = %i; IPv4 multicast address found", se->fd);
+
                        mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
                        mreq.imr_interface.s_addr = htonl (INADDR_ANY);
 
@@ -114,6 +105,8 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const sockent
                {
                        struct ipv6_mreq mreq;
 
+                       DBG ("fd = %i; IPv6 multicast address found", se->fd);
+
                        memcpy (&mreq.ipv6mr_multiaddr,
                                        &addr->sin6_addr,
                                        sizeof (addr->sin6_addr));
@@ -127,7 +120,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const sockent
                         * single interface; programs running on
                         * multihomed hosts may need to join the same
                         * group on more than one interface.*/
-                       mreq6.ipv6mr_interface = 0;
+                       mreq.ipv6mr_interface = 0;
 
                        if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
                                                &loop, sizeof (loop)) == -1)
@@ -199,11 +192,12 @@ int network_create_socket (const char *node, const char *service)
                        continue;
                }
 
-               assert (sizeof (struct sockaddr_storage) >= ai_ptr->addrlen);
+               assert (sizeof (struct sockaddr_storage) >= ai_ptr->ai_addrlen);
                memset (se->addr, '\0', sizeof (struct sockaddr_storage));
-               memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->addrlen);
-               se->addrlen = ai_ptr->addrlen;
+               memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+               se->addrlen = ai_ptr->ai_addrlen;
 
+               se->mode = operating_mode;
                se->fd   = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
                se->next = NULL;
 
@@ -216,7 +210,7 @@ int network_create_socket (const char *node, const char *service)
                }
 
                if (operating_mode == MODE_SERVER)
-                       if (network_bind_socket (se->fd, ai_ptr, se->addr) != 0)
+                       if (network_bind_socket (se, ai_ptr) != 0)
                        {
                                free (se->addr);
                                free (se);
@@ -225,7 +219,8 @@ int network_create_socket (const char *node, const char *service)
 
                if (socklist_tail == NULL)
                {
-                       socklist_head = socklist_tail = se;
+                       socklist_head = se;
+                       socklist_tail = se;
                }
                else
                {
@@ -245,51 +240,84 @@ int network_create_socket (const char *node, const char *service)
        return (num_added);
 }
 
+static int network_connect_default (void)
+{
+       int ret;
+
+       if (socklist_head != NULL)
+               return (0);
+
+       DBG ("socklist_head is NULL");
+
+       ret = 0;
+
+       if (network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT) > 0)
+               ret++;
+
+       /* Don't use IPv4 and IPv6 in parallel by default.. */
+       if ((operating_mode == MODE_CLIENT) && (ret != 0))
+               return (ret);
+
+       if (network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT) > 0)
+               ret++;
+
+       if (ret == 0)
+               ret = -1;
+
+       return (ret);
+}
+
 static int network_get_listen_socket (void)
 {
-       int    fd;
-       int    max_fd;
+       int fd;
+       int max_fd;
+       int status;
 
        fd_set readfds;
        sockent_t *se;
 
-       while (1)
+       if (socklist_head == NULL)
+               network_connect_default ();
+
+       FD_ZERO (&readfds);
+       max_fd = -1;
+       for (se = socklist_head; se != NULL; se = se->next)
        {
-               FD_ZERO (&readfds);
-               max_fd = -1;
-               for (se = socklist_head; se != NULL; se = se->next)
-               {
-                       FD_SET (se->fd, &readfds);
-                       if (se->fd >= max_fd)
-                               max_fd = se->fd + 1;
-               }
+               if (se->mode != operating_mode)
+                       continue;
 
-               if (max_fd == -1)
-               {
-                       syslog (LOG_WARNING, "No listen sockets found!");
-                       return (-1);
-               }
+               FD_SET (se->fd, &readfds);
+               if (se->fd >= max_fd)
+                       max_fd = se->fd + 1;
+       }
 
-               status = select (max_fd, &readfds, NULL, NULL, NULL);
+       if (max_fd == -1)
+       {
+               syslog (LOG_WARNING, "No listen sockets found!");
+               return (-1);
+       }
 
-               if ((status == -1) && (errno == EINTR))
-                       continue;
-               else if (status == -1)
-               {
+       status = select (max_fd, &readfds, NULL, NULL, NULL);
+
+       if (status == -1)
+       {
+               if (errno != EINTR)
                        syslog (LOG_ERR, "select: %s", strerror (errno));
-                       return (-1);
-               }
-               else
-                       break;
-       } /* while (true) */
+               return (-1);
+       }
 
        fd = -1;
        for (se = socklist_head; se != NULL; se = se->next)
+       {
+               if (se->mode != operating_mode)
+                       continue;
+
                if (FD_ISSET (se->fd, &readfds))
                {
                        fd = se->fd;
                        break;
                }
+       }
 
        if (fd == -1)
                syslog (LOG_WARNING, "No socket ready..?");
@@ -304,6 +332,7 @@ int network_receive (char **host, char **type, char **inst, char **value)
        char buffer[BUFF_SIZE];
 
        struct sockaddr_storage addr;
+       socklen_t               addrlen;
        int status;
 
        char *fields[4];
@@ -318,7 +347,7 @@ int network_receive (char **host, char **type, char **inst, char **value)
        if ((fd = network_get_listen_socket ()) < 0)
                return (-1);
 
-       if (recvfrom (fd, buffer, BUFF_SIZE, 0, (struct sockaddr *) &addr, sizeof (addr)) == -1)
+       if (recvfrom (fd, buffer, BUFF_SIZE, 0, (struct sockaddr *) &addr, &addrlen) == -1)
        {
                syslog (LOG_ERR, "recvfrom: %s", strerror (errno));
                return (-1);
@@ -330,7 +359,7 @@ int network_receive (char **host, char **type, char **inst, char **value)
                return (-1);
        }
 
-       status = getnameinfo ((struct sockaddr *) &addr, sizeof (addr),
+       status = getnameinfo ((struct sockaddr *) &addr, addrlen,
                        *host, BUFF_SIZE, NULL, 0, 0);
        if (status != 0)
        {
@@ -349,14 +378,14 @@ int network_receive (char **host, char **type, char **inst, char **value)
 
        if ((*type = strdup (fields[0])) == NULL)
        {
-               syslog (LOG_EMERG, "strdup: %s", strerror ());
+               syslog (LOG_EMERG, "strdup: %s", strerror (errno));
                free (*host); *host = NULL;
                return (-1);
        }
 
        if ((*inst = strdup (fields[1])) == NULL)
        {
-               syslog (LOG_EMERG, "strdup: %s", strerror ());
+               syslog (LOG_EMERG, "strdup: %s", strerror (errno));
                free (*host); *host = NULL;
                free (*type); *type = NULL;
                return (-1);
@@ -364,7 +393,7 @@ int network_receive (char **host, char **type, char **inst, char **value)
 
        if ((*value = strdup (fields[2])) == NULL)
        {
-               syslog (LOG_EMERG, "strdup: %s", strerror ());
+               syslog (LOG_EMERG, "strdup: %s", strerror (errno));
                free (*host); *host = NULL;
                free (*type); *type = NULL;
                free (*inst); *inst = NULL;
@@ -400,9 +429,15 @@ int network_send (char *type, char *inst, char *value)
        buf[buflen] = '\0';
        buflen++;
 
+       if (socklist_head == NULL)
+               network_connect_default ();
+
        ret = 0;
        for (se = socklist_head; se != NULL; se = se->next)
        {
+               if (se->mode != operating_mode)
+                       continue;
+
                DBG ("fd = %i", se->fd);
 
                while (1)
@@ -420,6 +455,7 @@ int network_send (char *type, char *inst, char *value)
                                else
                                {
                                        syslog (LOG_ERR, "sendto: %s", strerror (errno));
+                                       ret = -1;
                                        break;
                                }
                        }