X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fnetwork.c;h=98cb8eba100a8ccf19bb89d9dc39ce81d3f651e9;hb=7e711643c470b830f3f8e94512c0a7adf5418202;hp=eb32ad15081e811079fe864a1d999e0d09a4d77a;hpb=e94e1ca83a8ac255f045259ec898f944f9118430;p=collectd.git diff --git a/src/network.c b/src/network.c index eb32ad15..98cb8eba 100644 --- a/src/network.c +++ b/src/network.c @@ -1,6 +1,6 @@ /** * collectd - src/network.c - * Copyright (C) 2005-2009 Florian octo Forster + * Copyright (C) 2005-2013 Florian octo Forster * Copyright (C) 2009 Aman Gupta * * This program is free software; you can redistribute it and/or modify it @@ -18,7 +18,7 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster * Aman Gupta **/ @@ -31,6 +31,7 @@ #include "utils_fbhash.h" #include "utils_avltree.h" #include "utils_cache.h" +#include "utils_complain.h" #include "network.h" @@ -57,7 +58,24 @@ #endif #if HAVE_LIBGCRYPT +# include +# if defined __APPLE__ +/* default xcode compiler throws warnings even when deprecated functionality + * is not used. -Werror breaks the build because of erroneous warnings. + * http://stackoverflow.com/questions/10556299/compiler-warnings-with-libgcrypt-v1-5-0/12830209#12830209 + */ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +/* FreeBSD's copy of libgcrypt extends the existing GCRYPT_NO_DEPRECATED + * to properly hide all deprecated functionality. + * http://svnweb.freebsd.org/ports/head/security/libgcrypt/files/patch-src__gcrypt.h.in + */ +# define GCRYPT_NO_DEPRECATED # include +# if defined __APPLE__ +/* Re enable deprecation warnings */ +# pragma GCC diagnostic warning "-Wdeprecated-declarations" +# endif GCRY_THREAD_OPTION_PTHREAD_IMPL; #endif @@ -258,6 +276,7 @@ typedef struct receive_list_entry_s receive_list_entry_t; * Private variables */ static int network_config_ttl = 0; +/* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */ static size_t network_config_packet_size = 1452; static int network_config_forward = 0; static int network_config_stats = 0; @@ -295,14 +314,14 @@ static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER; * example). Only if neither is true, the stats_lock is acquired. The counters * are always read without holding a lock in the hope that writing 8 bytes to * memory is an atomic operation. */ -static uint64_t stats_octets_rx = 0; -static uint64_t stats_octets_tx = 0; -static uint64_t stats_packets_rx = 0; -static uint64_t stats_packets_tx = 0; -static uint64_t stats_values_dispatched = 0; -static uint64_t stats_values_not_dispatched = 0; -static uint64_t stats_values_sent = 0; -static uint64_t stats_values_not_sent = 0; +static derive_t stats_octets_rx = 0; +static derive_t stats_octets_tx = 0; +static derive_t stats_packets_rx = 0; +static derive_t stats_packets_tx = 0; +static derive_t stats_values_dispatched = 0; +static derive_t stats_values_not_dispatched = 0; +static derive_t stats_values_sent = 0; +static derive_t stats_values_not_sent = 0; static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER; /* @@ -350,6 +369,43 @@ static _Bool check_send_okay (const value_list_t *vl) /* {{{ */ return (!received); } /* }}} _Bool check_send_okay */ +static _Bool check_notify_received (const notification_t *n) /* {{{ */ +{ + notification_meta_t *ptr; + + for (ptr = n->meta; ptr != NULL; ptr = ptr->next) + if ((strcmp ("network:received", ptr->name) == 0) + && (ptr->type == NM_TYPE_BOOLEAN)) + return ((_Bool) ptr->nm_value.nm_boolean); + + return (0); +} /* }}} _Bool check_notify_received */ + +static _Bool check_send_notify_okay (const notification_t *n) /* {{{ */ +{ + static c_complain_t complain_forwarding = C_COMPLAIN_INIT_STATIC; + _Bool received = 0; + + if (n->meta == NULL) + return (1); + + received = check_notify_received (n); + + if (network_config_forward && received) + { + c_complain_once (LOG_ERR, &complain_forwarding, + "network plugin: A notification has been received via the network " + "forwarding if enabled. Forwarding of notifications is currently " + "not supported, because there is not loop-deteciton available. " + "Please contact the collectd mailing list if you need this " + "feature."); + } + + /* By default, only *send* value lists that were not *received* by the + * network plugin. */ + return (!received); +} /* }}} _Bool check_send_notify_okay */ + static int network_dispatch_values (value_list_t *vl, /* {{{ */ const char *username) { @@ -413,7 +469,44 @@ static int network_dispatch_values (value_list_t *vl, /* {{{ */ return (0); } /* }}} int network_dispatch_values */ +static int network_dispatch_notification (notification_t *n) /* {{{ */ +{ + int status; + + assert (n->meta == NULL); + + status = plugin_notification_meta_add_boolean (n, "network:received", 1); + if (status != 0) + { + ERROR ("network plugin: plugin_notification_meta_add_boolean failed."); + plugin_notification_meta_free (n->meta); + n->meta = NULL; + return (status); + } + + status = plugin_dispatch_notification (n); + + plugin_notification_meta_free (n->meta); + n->meta = NULL; + + return (status); +} /* }}} int network_dispatch_notification */ + #if HAVE_LIBGCRYPT +static void network_init_gcrypt (void) /* {{{ */ +{ + /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html + * Because you can't know in a library whether another library has + * already initialized the library */ + if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P)) + return; + + gcry_check_version (NULL); /* before calling any other functions */ + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + gcry_control (GCRYCTL_INIT_SECMEM, 32768); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED); +} /* }}} void network_init_gcrypt */ + static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */ const void *iv, size_t iv_size, const char *username) { @@ -599,7 +692,7 @@ static int write_part_number (char **ret_buffer, int *ret_buffer_len, part_header_t pkg_head; uint64_t pkg_value; - + int offset; packet_len = sizeof (pkg_head) + sizeof (pkg_value); @@ -703,7 +796,7 @@ static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len, exp_size = 3 * sizeof (uint16_t) + pkg_numval * (sizeof (uint8_t) + sizeof (value_t)); - if ((buffer_len < 0) || (buffer_len < exp_size)) + if (buffer_len < exp_size) { WARNING ("network plugin: parse_part_values: " "Packet too short: " @@ -787,9 +880,8 @@ static int parse_part_number (void **ret_buffer, size_t *ret_buffer_len, size_t exp_size = 2 * sizeof (uint16_t) + sizeof (uint64_t); uint16_t pkg_length; - uint16_t pkg_type; - if ((buffer_len < 0) || ((size_t) buffer_len < exp_size)) + if (buffer_len < exp_size) { WARNING ("network plugin: parse_part_number: " "Packet too short: " @@ -801,7 +893,7 @@ static int parse_part_number (void **ret_buffer, size_t *ret_buffer_len, memcpy ((void *) &tmp16, buffer, sizeof (tmp16)); buffer += sizeof (tmp16); - pkg_type = ntohs (tmp16); + /* pkg_type = ntohs (tmp16); */ memcpy ((void *) &tmp16, buffer, sizeof (tmp16)); buffer += sizeof (tmp16); @@ -827,9 +919,8 @@ static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len, size_t header_size = 2 * sizeof (uint16_t); uint16_t pkg_length; - uint16_t pkg_type; - if ((buffer_len < 0) || (buffer_len < header_size)) + if (buffer_len < header_size) { WARNING ("network plugin: parse_part_string: " "Packet too short: " @@ -841,7 +932,7 @@ static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len, memcpy ((void *) &tmp16, buffer, sizeof (tmp16)); buffer += sizeof (tmp16); - pkg_type = ntohs (tmp16); + /* pkg_type = ntohs (tmp16); */ memcpy ((void *) &tmp16, buffer, sizeof (tmp16)); buffer += sizeof (tmp16); @@ -917,6 +1008,8 @@ static int parse_packet (sockent_t *se, static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_len, int flags) { + static c_complain_t complain_no_users = C_COMPLAIN_INIT_STATIC; + char *buffer; size_t buffer_len; size_t buffer_offset; @@ -938,8 +1031,9 @@ static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */ if (se->data.server.userdb == NULL) { - NOTICE ("network plugin: Received signed network packet but can't verify " - "it because no user DB has been configured. Will accept it."); + c_complain (LOG_NOTICE, &complain_no_users, + "network plugin: Received signed network packet but can't verify it " + "because no user DB has been configured. Will accept it."); return (0); } @@ -1481,7 +1575,7 @@ static int parse_packet (sockent_t *se, /* {{{ */ } else { - plugin_dispatch_notification (&n); + network_dispatch_notification (&n); } } else if (pkg_type == TYPE_SEVERITY) @@ -1602,7 +1696,7 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai) sizeof (network_config_ttl)) != 0) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (ipv4-ttl): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } @@ -1623,7 +1717,7 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai) sizeof (network_config_ttl)) != 0) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt(ipv6-ttl): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -1670,7 +1764,7 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai &mreq, sizeof (mreq)) != 0) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (ipv4-multicast-if): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } @@ -1689,7 +1783,7 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai sizeof (se->interface)) != 0) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (ipv6-multicast-if): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -1700,9 +1794,9 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai } /* else: Not a multicast interface. */ -#if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE) if (se->interface != 0) { +#if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE) char interface_name[IFNAMSIZ]; if (if_indextoname (se->interface, interface_name) == NULL) @@ -1715,37 +1809,42 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai sizeof(interface_name)) == -1 ) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (bind-if): %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 " + WARNING ("network plugin: Cannot set the interface on a unicast " "socket because " # if !defined(SO_BINDTODEVICE) - "the the \"SO_BINDTODEVICE\" socket option " + "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) { +#if KERNEL_SOLARIS + char loop = 0; +#else int loop = 0; +#endif int yes = 1; /* allow multiple sockets to use the same PORT number */ if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (reuseaddr): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } @@ -1788,7 +1887,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int &loop, sizeof (loop)) == -1) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (multicast-loop): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -1798,7 +1897,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int &mreq, sizeof (mreq)) == -1) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (add-membership): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -1836,7 +1935,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int &loop, sizeof (loop)) == -1) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (ipv6-multicast-loop): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -1846,7 +1945,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int &mreq, sizeof (mreq)) == -1) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (ipv6-add-membership): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -1874,7 +1973,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int sizeof(interface_name)) == -1 ) { char errbuf[1024]; - ERROR ("setsockopt: %s", + ERROR ("network plugin: setsockopt (bind-if): %s", sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } @@ -1944,6 +2043,8 @@ static int sockent_open (sockent_t *se) /* {{{ */ { if (se->data.client.security_level > SECURITY_LEVEL_NONE) { + network_init_gcrypt (); + if ((se->data.client.username == NULL) || (se->data.client.password == NULL)) { @@ -1962,6 +2063,8 @@ static int sockent_open (sockent_t *se) /* {{{ */ { if (se->data.server.security_level > SECURITY_LEVEL_NONE) { + network_init_gcrypt (); + if (se->data.server.auth_file == NULL) { ERROR ("network plugin: Server socket with " @@ -2649,7 +2752,7 @@ static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */ return (-1); sstrncpy (vl_def->type_instance, vl->type_instance, sizeof (vl_def->type_instance)); } - + if (write_part_values (&buffer, &buffer_size, ds, vl) != 0) return (-1); @@ -3083,14 +3186,17 @@ static int network_config (oconfig_item_t *ci) /* {{{ */ } /* }}} int network_config */ static int network_notification (const notification_t *n, - user_data_t __attribute__((unused)) *user_data) + user_data_t __attribute__((unused)) *user_data) { char buffer[network_config_packet_size]; char *buffer_ptr = buffer; int buffer_free = sizeof (buffer); int status; - memset (buffer, '\0', sizeof (buffer)); + if (!check_send_notify_okay (n)) + return (0); + + memset (buffer, 0, sizeof (buffer)); status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME_HR, (uint64_t) n->time); @@ -3105,7 +3211,7 @@ static int network_notification (const notification_t *n, if (strlen (n->host) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_HOST, - n->host, strlen (n->host)); + n->host, strlen (n->host)); if (status != 0) return (-1); } @@ -3113,7 +3219,7 @@ static int network_notification (const notification_t *n, if (strlen (n->plugin) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_PLUGIN, - n->plugin, strlen (n->plugin)); + n->plugin, strlen (n->plugin)); if (status != 0) return (-1); } @@ -3121,8 +3227,8 @@ static int network_notification (const notification_t *n, if (strlen (n->plugin_instance) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, - TYPE_PLUGIN_INSTANCE, - n->plugin_instance, strlen (n->plugin_instance)); + TYPE_PLUGIN_INSTANCE, + n->plugin_instance, strlen (n->plugin_instance)); if (status != 0) return (-1); } @@ -3130,7 +3236,7 @@ static int network_notification (const notification_t *n, if (strlen (n->type) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE, - n->type, strlen (n->type)); + n->type, strlen (n->type)); if (status != 0) return (-1); } @@ -3138,7 +3244,7 @@ static int network_notification (const notification_t *n, if (strlen (n->type_instance) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE_INSTANCE, - n->type_instance, strlen (n->type_instance)); + n->type_instance, strlen (n->type_instance)); if (status != 0) return (-1); } @@ -3197,15 +3303,15 @@ static int network_shutdown (void) static int network_stats_read (void) /* {{{ */ { - uint64_t copy_octets_rx; - uint64_t copy_octets_tx; - uint64_t copy_packets_rx; - uint64_t copy_packets_tx; - uint64_t copy_values_dispatched; - uint64_t copy_values_not_dispatched; - uint64_t copy_values_sent; - uint64_t copy_values_not_sent; - uint64_t copy_receive_list_length; + derive_t copy_octets_rx; + derive_t copy_octets_tx; + derive_t copy_packets_rx; + derive_t copy_packets_tx; + derive_t copy_values_dispatched; + derive_t copy_values_not_dispatched; + derive_t copy_values_sent; + derive_t copy_values_not_sent; + derive_t copy_receive_list_length; value_list_t vl = VALUE_LIST_INIT; value_t values[2]; @@ -3223,19 +3329,18 @@ static int network_stats_read (void) /* {{{ */ vl.values = values; vl.values_len = 2; vl.time = 0; - vl.interval = interval_g; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "network", sizeof (vl.plugin)); /* Octets received / sent */ - vl.values[0].counter = (counter_t) copy_octets_rx; - vl.values[1].counter = (counter_t) copy_octets_tx; + vl.values[0].derive = (derive_t) copy_octets_rx; + vl.values[1].derive = (derive_t) copy_octets_tx; sstrncpy (vl.type, "if_octets", sizeof (vl.type)); plugin_dispatch_values (&vl); /* Packets received / send */ - vl.values[0].counter = (counter_t) copy_packets_rx; - vl.values[1].counter = (counter_t) copy_packets_tx; + vl.values[0].derive = (derive_t) copy_packets_rx; + vl.values[1].derive = (derive_t) copy_packets_tx; sstrncpy (vl.type, "if_packets", sizeof (vl.type)); plugin_dispatch_values (&vl); @@ -3283,9 +3388,7 @@ static int network_init (void) have_init = 1; #if HAVE_LIBGCRYPT - gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); - gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + network_init_gcrypt (); #endif if (network_config_stats != 0) @@ -3319,7 +3422,7 @@ static int network_init (void) if (dispatch_thread_running == 0) { int status; - status = pthread_create (&dispatch_thread_id, + status = plugin_thread_create (&dispatch_thread_id, NULL /* no attributes */, dispatch_thread, NULL /* no argument */); @@ -3339,7 +3442,7 @@ static int network_init (void) if (receive_thread_running == 0) { int status; - status = pthread_create (&receive_thread_id, + status = plugin_thread_create (&receive_thread_id, NULL /* no attributes */, receive_thread, NULL /* no argument */); @@ -3359,7 +3462,7 @@ static int network_init (void) return (0); } /* int network_init */ -/* +/* * The flush option of the network plugin cannot flush individual identifiers. * All the values are added to a buffer and sent when the buffer is full, the * requested value may or may not be in there, it's not worth finding out. We