From: Florian Forster Date: Wed, 7 Apr 2010 09:55:24 +0000 (+0200) Subject: Merge branch 'collectd-4.9' X-Git-Tag: collectd-4.10.0~20 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=593ea76dca367478b92e17f91e663fe7c67b4df9;hp=-c;p=collectd.git Merge branch 'collectd-4.9' --- 593ea76dca367478b92e17f91e663fe7c67b4df9 diff --combined README index 1dd09df4,14e11cf2..7d1a64a3 --- a/README +++ b/README @@@ -57,10 -57,6 +57,10 @@@ Feature Retrieves JSON data via cURL and parses it according to user configuration. + - curl_xml + Retrieves XML data via cURL and parses it according to user + configuration. + - dbi Executes SQL statements on various databases and interprets the returned data. @@@ -147,10 -143,6 +147,10 @@@ Memory utilization: Memory occupied by running processes, page cache, buffer cache and free. + - modbus + Reads values from Modbus/TCP enabled devices. Supports reading values + from multiple "slaves" so gateway devices can be used. + - multimeter Information provided by serial multimeters, such as the `Metex M-4650CR'. @@@ -301,7 -293,7 +301,7 @@@ - zfs_arc Statistics for ZFS' “Adaptive Replacement Cache” (ARC). - * Output can be written or send to various destinations by the following + * Output can be written or sent to various destinations by the following plugins: - csv @@@ -434,7 -426,7 +434,7 @@@ network plugins, makes sure your resources are used efficiently. Also, since collectd is programmed multithreaded it benefits from hyperthreading and multicore processors and makes sure that the daemon isn't idle if only - one plugins waits for an IO-operation to complete. + one plugin waits for an IO-operation to complete. * Once set up, hardly any maintenance is necessary. Setup is kept as easy as possible and the default values should be okay for most users. @@@ -545,15 -537,11 +545,15 @@@ Prerequisite Used by the `memcachec' plugin to connect to a memcache daemon. + * libmodbus (optional) + Used by the `modbus' plugin to communicate with Modbus/TCP devices. + + * libmysqlclient (optional) Unsurprisingly used by the `mysql' plugin. - * libnatapp (optional) + * libnetapp (optional) Required for the “netapp” plugin. This library is part of the “Manage ONTAP SDK” published by NetApp. diff --combined configure.in index f3206cb6,efb1e24c..32245265 --- a/configure.in +++ b/configure.in @@@ -477,7 -477,7 +477,7 @@@ AC_HEADER_TIM # Checks for library functions. # AC_PROG_GCC_TRADITIONAL -AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf) +AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf if_indextoname) AC_FUNC_STRERROR_R @@@ -550,8 -550,16 +550,16 @@@ AC_CHECK_FUNCS(socket, [], AC_CHECK_LIB AM_CONDITIONAL(BUILD_WITH_LIBSOCKET, test "x$socket_needs_socket" = "xyes") nanosleep_needs_rt="no" - AC_CHECK_FUNCS(nanosleep, [], AC_CHECK_LIB(rt, nanosleep, [nanosleep_needs_rt="yes"], AC_MSG_ERROR(cannot find nanosleep))) + nanosleep_needs_posix4="no" + AC_CHECK_FUNCS(nanosleep, + [], + AC_CHECK_LIB(rt, nanosleep, + [nanosleep_needs_rt="yes"], + AC_CHECK_LIB(posix4, nanosleep, + [nanosleep_needs_posix4="yes"], + AC_MSG_ERROR(cannot find nanosleep)))) AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$nanosleep_needs_rt" = "xyes") + AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$nanosleep_needs_posix4" = "xyes") AC_CHECK_FUNCS(sysctl, [have_sysctl="yes"], [have_sysctl="no"]) AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"]) @@@ -971,13 -979,6 +979,13 @@@ AC_CHECK_MEMBERS([struct net_device_sta #include ]) +AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], + [], + [ + #include + #include + ]) + AC_CHECK_MEMBERS([struct kinfo_proc.ki_pid, struct kinfo_proc.ki_rssize, struct kinfo_proc.ki_rusage], [ AC_DEFINE(HAVE_STRUCT_KINFO_PROC_FREEBSD, 1, @@@ -1853,98 -1854,6 +1861,98 @@@ f AM_CONDITIONAL(BUILD_WITH_LIBMEMCACHED, test "x$with_libmemcached" = "xyes") # }}} +# --with-libmodbus {{{ +with_libmodbus_config="" +with_libmodbus_cflags="" +with_libmodbus_libs="" +AC_ARG_WITH(libmodbus, [AS_HELP_STRING([--with-libmodbus@<:@=PREFIX@:>@], [Path to the modbus library.])], +[ + if test "x$withval" = "xno" + then + with_libmodbus="no" + else if test "x$withval" = "xyes" + then + with_libmodbus="use_pkgconfig" + else if test -d "$with_libmodbus/lib" + then + AC_MSG_NOTICE([Not checking for libmodbus: Manually configured]) + with_libmodbus_cflags="-I$withval/include" + with_libmodbus_libs="-L$withval/lib -lmodbus" + with_libmodbus="yes" + fi; fi; fi +], +[with_libmodbus="use_pkgconfig"]) + +# configure using pkg-config +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + if test "x$PKG_CONFIG" = "x" + then + with_libmodbus="no (Don't have pkg-config)" + fi +fi +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + AC_MSG_NOTICE([Checking for modbus using $PKG_CONFIG]) + $PKG_CONFIG --exists 'modbus' 2>/dev/null + if test $? -ne 0 + then + with_libmodbus="no (pkg-config doesn't know library)" + fi +fi +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + with_libmodbus_cflags="`$PKG_CONFIG --cflags 'modbus'`" + if test $? -ne 0 + then + with_libmodbus="no ($PKG_CONFIG failed)" + fi + with_libmodbus_libs="`$PKG_CONFIG --libs 'modbus'`" + if test $? -ne 0 + then + with_libmodbus="no ($PKG_CONFIG failed)" + fi +fi +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + with_libmodbus="yes" +fi + +# with_libmodbus_cflags and with_libmodbus_libs are set up now, let's do +# the actual checks. +if test "x$with_libmodbus" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags" + + AC_CHECK_HEADERS(modbus/modbus.h, [], [with_libmodbus="no (modbus/modbus.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_libmodbus" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + + CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags" + LDFLAGS="$LDFLAGS $with_libmodbus_libs" + + AC_CHECK_LIB(modbus, modbus_init_tcp, + [with_libmodbus="yes"], + [with_libmodbus="no (symbol modbus_init_tcp not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_libmodbus" = "xyes" +then + BUILD_WITH_LIBMODBUS_CFLAGS="$with_libmodbus_cflags" + BUILD_WITH_LIBMODBUS_LIBS="$with_libmodbus_libs" + AC_SUBST(BUILD_WITH_LIBMODBUS_CFLAGS) + AC_SUBST(BUILD_WITH_LIBMODBUS_LIBS) +fi +# }}} + # --with-libmysql {{{ with_mysql_config="mysql_config" with_mysql_cflags="" @@@ -2890,7 -2799,7 +2898,7 @@@ f if test "x$with_python" = "xyes" then AC_MSG_CHECKING([for Python CPPFLAGS]) - python_include_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_python_inc()" | "$with_python_prog" 2>&1` + python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1` python_config_status=$? if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x" @@@ -2913,7 -2822,7 +2921,7 @@@ f if test "x$with_python" = "xyes" then AC_MSG_CHECKING([for Python LDFLAGS]) - python_library_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0)" | "$with_python_prog" 2>&1` + python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1` python_config_status=$? if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x" @@@ -2928,7 -2837,7 +2936,7 @@@ f if test "x$with_python" = "xyes" then AC_MSG_CHECKING([for Python LIBS]) - python_library_flags=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0)" | "$with_python_prog" 2>&1` + python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1` python_config_status=$? if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x" @@@ -3888,7 -3797,7 +3896,7 @@@ AC_DEFUN enable_plugin="yes" force="yes" else - enable_plugin="no" + enable_plugin="no (disabled on command line)" fi; fi ], [ @@@ -3941,7 -3850,6 +3949,7 @@@ plugin_contextswitch="no plugin_cpu="no" plugin_cpufreq="no" plugin_curl_json="no" +plugin_curl_xml="no" plugin_df="no" plugin_disk="no" plugin_entropy="no" @@@ -4081,11 -3989,6 +4089,11 @@@ the plugin_curl_json="yes" fi +if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes" +then + plugin_curl_xml="yes" +fi + if test "x$have_processor_info" = "xyes" then plugin_cpu="yes" @@@ -4239,7 -4142,6 +4247,7 @@@ AC_PLUGIN([cpu], [$plugin_cpu] AC_PLUGIN([csv], [yes], [CSV output plugin]) AC_PLUGIN([curl], [$with_libcurl], [CURL generic web statistics]) AC_PLUGIN([curl_json], [$plugin_curl_json], [CouchDB statistics]) +AC_PLUGIN([curl_xml], [$plugin_curl_xml], [CURL generic xml statistics]) AC_PLUGIN([dbi], [$with_libdbi], [General database statistics]) AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics]) AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics]) @@@ -4270,7 -4172,6 +4278,7 @@@ AC_PLUGIN([mbmon], [yes] AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics]) AC_PLUGIN([memcached], [yes], [memcached statistics]) AC_PLUGIN([memory], [$plugin_memory], [Memory usage]) +AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin]) AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values]) AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics]) AC_PLUGIN([netapp], [$with_libnetapp], [NetApp plugin]) @@@ -4504,7 -4405,6 +4512,7 @@@ Configuration libkstat . . . . . . $with_kstat libkvm . . . . . . . $with_libkvm libmemcached . . . . $with_libmemcached + libmodbus . . . . . . $with_libmodbus libmysql . . . . . . $with_libmysql libnetapp . . . . . . $with_libnetapp libnetlink . . . . . $with_libnetlink @@@ -4552,7 -4452,6 +4560,7 @@@ csv . . . . . . . . . $enable_csv curl . . . . . . . . $enable_curl curl_json . . . . . . $enable_curl_json + curl_xml . . . . . . $enable_curl_xml dbi . . . . . . . . . $enable_dbi df . . . . . . . . . $enable_df disk . . . . . . . . $enable_disk @@@ -4583,7 -4482,6 +4591,7 @@@ memcachec . . . . . . $enable_memcachec memcached . . . . . . $enable_memcached memory . . . . . . . $enable_memory + modbus . . . . . . . $enable_modbus multimeter . . . . . $enable_multimeter mysql . . . . . . . . $enable_mysql netapp . . . . . . . $enable_netapp diff --combined src/Makefile.am index 68db92eb,4c3f5e97..1bf550e7 --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -53,6 -53,9 +53,9 @@@ collectd_DEPENDENCIES if BUILD_WITH_LIBRT collectd_LDADD += -lrt endif + if BUILD_WITH_LIBPOSIX4 + collectd_LDADD += -lposix4 + endif if BUILD_WITH_LIBSOCKET collectd_LDADD += -lsocket endif @@@ -257,17 -260,6 +260,17 @@@ collectd_LDADD += "-dlopen" curl_json.l collectd_DEPENDENCIES += curl_json.la endif +if BUILD_PLUGIN_CURL_XML +pkglib_LTLIBRARIES += curl_xml.la +curl_xml_la_SOURCES = curl_xml.c +curl_xml_la_LDFLAGS = -module -avoid-version +curl_xml_la_CFLAGS = $(AM_CFLAGS) \ + $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) +curl_xml_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS) +collectd_LDADD += "-dlopen" curl_xml.la +collectd_DEPENDENCIES += curl_xml.la +endif + if BUILD_PLUGIN_DBI pkglib_LTLIBRARIES += dbi.la dbi_la_SOURCES = dbi.c \ @@@ -598,16 -590,6 +601,16 @@@ memory_la_LIBADD += -lperfsta endif endif +if BUILD_PLUGIN_MODBUS +pkglib_LTLIBRARIES += modbus.la +modbus_la_SOURCES = modbus.c +modbus_la_LDFLAGS = -module -avoid-version +modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS) +modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS) +collectd_LDADD += "-dlopen" modbus.la +collectd_DEPENDENCIES += modbus.la +endif + if BUILD_PLUGIN_MULTIMETER pkglib_LTLIBRARIES += multimeter.la multimeter_la_SOURCES = multimeter.c diff --combined src/collectd.conf.in index cd7839d7,c047a1a6..0d95ddf3 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@@ -63,7 -63,6 +63,7 @@@ FQDNLookup tru @LOAD_PLUGIN_CSV@LoadPlugin csv #@BUILD_PLUGIN_CURL_TRUE@LoadPlugin curl #@BUILD_PLUGIN_CURL_JSON_TRUE@LoadPlugin curl_json +#@BUILD_PLUGIN_CURL_XML_TRUE@LoadPlugin curl_xml #@BUILD_PLUGIN_DBI_TRUE@LoadPlugin dbi #@BUILD_PLUGIN_DF_TRUE@LoadPlugin df #@BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk @@@ -232,25 -231,6 +232,25 @@@ # # +# +# +# Host "my_host" +# Instance "some_instance" +# User "collectd" +# Password "thaiNg0I" +# VerifyPeer true +# VerifyHost true +# CACert "/path/to/ca.crt" +# +# +# Type "magic_level" +# #InstancePrefix "prefix-" +# InstanceFrom "td[1]" +# ValuesFrom "td[2]/span[@class=\"level\"]" +# +# +# + # # # Statement "SELECT 'customers' AS c_key, COUNT(*) AS c_value FROM customers_tbl" @@@ -582,7 -562,7 +582,7 @@@ # # IncludeDir "/my/include/path" - # BaseName "Collectd::Plugin" + # BaseName "Collectd::Plugins" # EnableDebugger "" # LoadPlugin Monitorus # LoadPlugin OpenVZ @@@ -685,10 -665,6 +685,10 @@@ # Password "dozaiTh4" # CollectInterface true # CollectRegistrationTable true +# CollectCPULoad true +# CollectMemory true +# CollectDF true +# CollectDisk true # # @@@ -784,7 -760,6 +784,7 @@@ # # # Regex "\\" +# ExcludeRegex "\\.*mail_spool defer" # DSType "CounterInc" # Type "counter" # Instance "local_user" diff --combined src/network.c index 96053a13,a3ec5d94..74325a29 --- a/src/network.c +++ b/src/network.c @@@ -52,9 -52,6 +52,9 @@@ #if HAVE_POLL_H # include #endif +#if HAVE_NET_IF_H +# include +#endif #if HAVE_LIBGCRYPT # include @@@ -121,7 -118,6 +121,7 @@@ typedef struct socken char *node; char *service; + int interface; union { @@@ -1144,7 -1140,10 +1144,10 @@@ static int parse_part_encr_aes256 (sock cypher = network_get_aes256_cypher (se, pea.iv, sizeof (pea.iv), pea.username); if (cypher == NULL) + { + sfree (pea.username); return (-1); + } payload_len = part_size - (PART_ENCRYPTION_AES256_SIZE + username_len); assert (payload_len > 0); @@@ -1156,6 -1155,7 +1159,7 @@@ /* in = */ NULL, /* in len = */ 0); if (err != 0) { + sfree (pea.username); ERROR ("network plugin: gcry_cipher_decrypt returned: %s", gcry_strerror (err)); return (-1); @@@ -1174,6 -1174,7 +1178,7 @@@ buffer + buffer_offset, payload_len); if (memcmp (hash, pea.hash, sizeof (hash)) != 0) { + sfree (pea.username); ERROR ("network plugin: Decryption failed: Checksum mismatch."); return (-1); } @@@ -1185,6 -1186,8 +1190,8 @@@ *ret_buffer = buffer + part_size; *ret_buffer_len = buffer_len - part_size; + sfree (pea.username); + return (0); } /* }}} int parse_part_encr_aes256 */ /* #endif HAVE_LIBGCRYPT */ @@@ -1553,7 -1556,7 +1560,7 @@@ static int network_set_ttl (const socke if (setsockopt (se->data.client.fd, IPPROTO_IP, optname, &network_config_ttl, - sizeof (network_config_ttl)) == -1) + sizeof (network_config_ttl)) != 0) { char errbuf[1024]; ERROR ("setsockopt: %s", @@@ -1574,7 -1577,7 +1581,7 @@@ if (setsockopt (se->data.client.fd, IPPROTO_IPV6, optname, &network_config_ttl, - sizeof (network_config_ttl)) == -1) + sizeof (network_config_ttl)) != 0) { char errbuf[1024]; ERROR ("setsockopt: %s", @@@ -1587,110 -1590,7 +1594,110 @@@ return (0); } /* int network_set_ttl */ -static int network_bind_socket (int fd, const struct addrinfo *ai) +static int network_set_interface (const sockent_t *se, const struct addrinfo *ai) /* {{{ */ +{ + DEBUG ("network plugin: network_set_interface: interface index = %i;", + se->interface); + + assert (se->type == SOCKENT_TYPE_CLIENT); + + if (ai->ai_family == AF_INET) + { + struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr; + + 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 = se->interface; +#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 (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF, + &mreq, sizeof (mreq)) != 0) + { + char errbuf[1024]; + ERROR ("setsockopt: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + + return (0); + } + } + else if (ai->ai_family == AF_INET6) + { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr; + + if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr)) + { + if (setsockopt (se->data.client.fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, + &se->interface, + sizeof (se->interface)) != 0) + { + char errbuf[1024]; + ERROR ("setsockopt: %s", + sstrerror (errno, errbuf, + sizeof (errbuf))); + return (-1); + } + + return (0); + } + } + + /* else: Not a multicast interface. */ +#if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE) + if (se->interface != 0) + { + char interface_name[IFNAMSIZ]; + + if (if_indextoname (se->interface, interface_name) == NULL) + return (-1); + + DEBUG ("network plugin: Binding socket to interface %s", interface_name); + + if (setsockopt (se->data.client.fd, SOL_SOCKET, SO_BINDTODEVICE, + interface_name, + sizeof(interface_name)) == -1 ) + { + char errbuf[1024]; + ERROR ("setsockopt: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + } +/* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */ + +#else + WARNING ("network plugin: Cannot set the interface on a unicast " + "socket because " +# if !defined(SO_BINDTODEVICE) + "the the \"SO_BINDTODEVICE\" socket option " +# else + "the \"if_indextoname\" function " +# endif + "is not available on your system."); +#endif + + return (0); +} /* }}} network_set_interface */ + +static int network_bind_socket (int fd, const struct addrinfo *ai, const int interface_idx) { int loop = 0; int yes = 1; @@@ -1719,24 -1619,12 +1726,24 @@@ struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr; if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr))) { +#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX + struct ip_mreqn mreq; +#else struct ip_mreq mreq; +#endif DEBUG ("fd = %i; IPv4 multicast address found", fd); mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr; - mreq.imr_interface.s_addr = htonl (INADDR_ANY); +#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX + /* Set the interface using the interface index if + * possible (available). Unfortunately, the struct + * ip_mreqn is not portable. */ + mreq.imr_address.s_addr = ntohl (INADDR_ANY); + mreq.imr_ifindex = interface_idx; +#else + mreq.imr_interface.s_addr = ntohl (INADDR_ANY); +#endif if (setsockopt (fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof (loop)) == -1) @@@ -1757,8 -1645,6 +1764,8 @@@ sizeof (errbuf))); return (-1); } + + return (0); } } else if (ai->ai_family == AF_INET6) @@@ -1784,7 -1670,7 +1791,7 @@@ * single interface; programs running on * multihomed hosts may need to join the same * group on more than one interface.*/ - mreq.ipv6mr_interface = 0; + mreq.ipv6mr_interface = interface_idx; if (setsockopt (fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof (loop)) == -1) @@@ -1805,35 -1691,8 +1812,35 @@@ sizeof (errbuf))); return (-1); } + + return (0); + } + } + +#if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE) + /* if a specific interface was set, bind the socket to it. But to avoid + * possible problems with multicast routing, only do that for non-multicast + * addresses */ + if (interface_idx != 0) + { + char interface_name[IFNAMSIZ]; + + if (if_indextoname (interface_idx, interface_name) == NULL) + return (-1); + + DEBUG ("fd = %i; Binding socket to interface %s", fd, interface_name); + + if (setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, + interface_name, + sizeof(interface_name)) == -1 ) + { + char errbuf[1024]; + ERROR ("setsockopt: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); } } +#endif /* HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */ return (0); } /* int network_bind_socket */ @@@ -1850,7 -1709,6 +1857,7 @@@ static int sockent_init (sockent_t *se se->type = SOCKENT_TYPE_CLIENT; se->node = NULL; se->service = NULL; + se->interface = 0; se->next = NULL; if (type == SOCKENT_TYPE_SERVER) @@@ -1999,7 -1857,7 +2006,7 @@@ static int sockent_open (sockent_t *se continue; } - status = network_bind_socket (*tmp, ai_ptr); + status = network_bind_socket (*tmp, ai_ptr, se->interface); if (status != 0) { close (*tmp); @@@ -2039,7 -1897,6 +2046,7 @@@ se->data.client.addrlen = ai_ptr->ai_addrlen; network_set_ttl (se, ai_ptr); + network_set_interface (se, ai_ptr); /* We don't open more than one write-socket per * node/service pair.. */ @@@ -2751,25 -2608,6 +2758,25 @@@ static int network_config_set_ttl (cons return (0); } /* }}} int network_config_set_ttl */ +static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */ + int *interface) +{ + if ((ci->values_num != 1) + || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + WARNING ("network plugin: The `Interface' config option needs exactly " + "one string argument."); + return (-1); + } + + if (interface == NULL) + return (-1); + + *interface = if_nametoindex (ci->values[0].value.string); + + return (0); +} /* }}} int network_config_set_interface */ + static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */ { int tmp; @@@ -2881,10 -2719,6 +2888,10 @@@ static int network_config_add_listen (c &se->data.server.security_level); else #endif /* HAVE_LIBGCRYPT */ + if (strcasecmp ("Interface", child->key) == 0) + network_config_set_interface (child, + &se->interface); + else { WARNING ("network plugin: Option `%s' is not allowed here.", child->key); @@@ -2963,10 -2797,6 +2970,10 @@@ static int network_config_add_server (c &se->data.client.security_level); else #endif /* HAVE_LIBGCRYPT */ + if (strcasecmp ("Interface", child->key) == 0) + network_config_set_interface (child, + &se->interface); + else { WARNING ("network plugin: Option `%s' is not allowed here.", child->key); diff --combined src/snmp.c index 24707611,fee2f6d5..fdb7c658 --- a/src/snmp.c +++ b/src/snmp.c @@@ -655,9 -655,8 +655,9 @@@ static int csnmp_config_add_host (oconf if (hd->interval != 0) cb_interval.tv_sec = (time_t) hd->interval; - status = plugin_register_complex_read (cb_name, csnmp_read_host, - /* interval = */ &cb_interval, /* user_data = */ &cb_data); + status = plugin_register_complex_read (/* group = */ NULL, cb_name, + csnmp_read_host, /* interval = */ &cb_interval, + /* user_data = */ &cb_data); if (status != 0) { ERROR ("snmp plugin: Registering complex read function failed."); @@@ -1128,7 -1127,7 +1128,7 @@@ static int csnmp_dispatch_table (host_d char temp[DATA_MAX_NAME_LEN]; if (instance_list_ptr == NULL) - ssnprintf (temp, sizeof (temp), "%u", (uint32_t) subid); + ssnprintf (temp, sizeof (temp), "%"PRIu32, (uint32_t) subid); else sstrncpy (temp, instance_list_ptr->instance, sizeof (temp));