X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fnetwork.c;h=22e911a87b8e4d4fe89d805abc9c9559ce2463c6;hb=44d73d6556833bcfbc4678a01731aafee95c3caf;hp=3a88b60518e49eb3dcb1da456f408c8dc170e238;hpb=586eed684dc5529c74d6e81f80e226c122494495;p=collectd.git diff --git a/src/network.c b/src/network.c index 3a88b605..22e911a8 100644 --- a/src/network.c +++ b/src/network.c @@ -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 @@ -33,18 +33,23 @@ #include "network.h" #include "common.h" +#include "configfile.h" #include "utils_debug.h" /* 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 { @@ -57,6 +62,63 @@ typedef struct sockent static sockent_t *socklist_head = NULL; +static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai) +{ + char *ttl_str; + int ttl_int; + + 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)) + { + 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; @@ -152,18 +214,28 @@ 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; /* XXX is this right here?!? */ + ai_hints.ai_protocol = IPPROTO_UDP; if ((ai_return = getaddrinfo (node, service, &ai_hints, &ai_list)) != 0) { @@ -209,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) { @@ -346,6 +424,7 @@ int network_receive (char **host, char **type, char **inst, char **value) if ((fd = network_get_listen_socket ()) < 0) return (-1); + addrlen = sizeof (addr); if (recvfrom (fd, buffer, BUFF_SIZE, 0, (struct sockaddr *) &addr, &addrlen) == -1) { syslog (LOG_ERR, "recvfrom: %s", strerror (errno)); @@ -437,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,