Code

src/Makefile.am: Added utils_dns.h to dns_la_SOURCES.
[collectd.git] / src / network.c
index cecf0bad743186158393292c7676621b3556fd3c..22e911a87b8e4d4fe89d805abc9c9559ce2463c6 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/network.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2005,2006  Florian octo Forster
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 /* 1500 - 40 - 8  =  Ethernet packet - IPv6 header - UDP header */
 /* #define BUFF_SIZE 1452 */
 
+#ifndef IPV6_ADD_MEMBERSHIP
+# ifdef IPV6_JOIN_GROUP
+#  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+# else
+#  error "Neither IP_ADD_MEMBERSHIP nor IPV6_JOIN_GROUP is defined"
+# endif
+#endif /* !IP_ADD_MEMBERSHIP */
+
 #define BUFF_SIZE 4096
 
-#ifdef HAVE_LIBRRD
 extern int operating_mode;
-#else
-static int operating_mode = MODE_CLIENT;
-#endif
 
 typedef struct sockent
 {
@@ -58,19 +62,66 @@ typedef struct sockent
 
 static sockent_t *socklist_head = NULL;
 
-static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
+static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
 {
-       int loop = 1;
-
        char *ttl_str;
        int   ttl_int;
 
-       ttl_str = cf_get_option ("MulticastTTL", NULL);
-       ttl_int = 0;
-       if (ttl_str != NULL)
-               ttl_int = atoi (ttl_str);
+       ttl_str = cf_get_option ("TimeToLive", NULL);
+       if (ttl_str == NULL)
+               return (-1);
+
+       ttl_int = atoi (ttl_str);
        if ((ttl_int < 1) || (ttl_int > 255))
-               ttl_int = NET_DEFAULT_MC_TTL;
+       {
+               syslog (LOG_WARNING, "A TTL value of %i is invalid.", ttl_int);
+               return (-1);
+       }
+
+       DBG ("ttl = %i", ttl_int);
+
+       if (ai->ai_family == AF_INET)
+       {
+               struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
+               int optname;
+
+               if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+                       optname = IP_MULTICAST_TTL;
+               else
+                       optname = IP_TTL;
+
+               if (setsockopt (se->fd, IPPROTO_IP, optname,
+                                       &ttl_int, sizeof (ttl_int)) == -1)
+               {
+                       syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
+                       return (-1);
+               }
+       }
+       else if (ai->ai_family == AF_INET6)
+       {
+               /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
+               int optname;
+
+               if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+                       optname = IPV6_MULTICAST_HOPS;
+               else
+                       optname = IPV6_UNICAST_HOPS;
+
+               if (setsockopt (se->fd, IPPROTO_IPV6, optname,
+                                       &ttl_int, sizeof (ttl_int)) == -1)
+               {
+                       syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
+                       return (-1);
+               }
+       }
+
+       return (0);
+}
+
+static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
+{
+       int loop = 1;
 
        DBG ("fd = %i; calling `bind'", se->fd);
 
@@ -99,14 +150,6 @@ static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
                                return (-1);
                        }
 
-                       /* IP_MULTICAST_TTL */
-                       if (setsockopt (se->fd, IPPROTO_IP, IP_MULTICAST_TTL,
-                                               &ttl_int, sizeof (ttl_int)) == -1)
-                       {
-                               syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
-                               return (-1);
-                       }
-
                        if (setsockopt (se->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                                                &mreq, sizeof (mreq)) == -1)
                        {
@@ -147,13 +190,6 @@ static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
                                return (-1);
                        }
 
-                       if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
-                                               &ttl_int, sizeof (ttl_int)) == -1)
-                       {
-                               syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
-                               return (-1);
-                       }
-
                        if (setsockopt (se->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
                                                &mreq, sizeof (mreq)) == -1)
                        {
@@ -178,15 +214,25 @@ int network_create_socket (const char *node, const char *service)
 
        DBG ("node = %s, service = %s", node, service);
 
-       if (operating_mode == MODE_LOCAL)
+       if (operating_mode == MODE_LOCAL || operating_mode == MODE_LOG)
+       {
+               syslog (LOG_WARNING, "network_create_socket: There is no point opening a socket when you are in mode `%s'.",
+                               operating_mode == MODE_LOCAL ? "Local" : "Log");
                return (-1);
+       }
 
        socklist_tail = socklist_head;
        while ((socklist_tail != NULL) && (socklist_tail->next != NULL))
                socklist_tail = socklist_tail->next;
 
        memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG;
+       ai_hints.ai_flags    = 0;
+#ifdef AI_PASSIVE
+       ai_hints.ai_flags |= AI_PASSIVE;
+#endif
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
        ai_hints.ai_family   = PF_UNSPEC;
        ai_hints.ai_socktype = SOCK_DGRAM;
        ai_hints.ai_protocol = IPPROTO_UDP;
@@ -235,12 +281,18 @@ int network_create_socket (const char *node, const char *service)
                }
 
                if (operating_mode == MODE_SERVER)
+               {
                        if (network_bind_socket (se, ai_ptr) != 0)
                        {
                                free (se->addr);
                                free (se);
                                continue;
                        }
+               }
+               else if (operating_mode == MODE_CLIENT)
+               {
+                       network_set_ttl (se, ai_ptr);
+               }
 
                if (socklist_tail == NULL)
                {
@@ -464,8 +516,6 @@ int network_send (char *type, char *inst, char *value)
                if (se->mode != operating_mode)
                        continue;
 
-               DBG ("fd = %i", se->fd);
-
                while (1)
                {
                        status = sendto (se->fd, buf, buflen, 0,