X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fnetwork.c;h=e5b8b3a84f58e14c5c8d615fd8841feb318c8d08;hp=b5f3d4893abcd63d49e249fde0fdbb328bec6096;hb=de407dd4e036f73e9bd4658af9d71f504fc11109;hpb=a6f29de68fe19614b0aa90e920e99d72cb0f4468 diff --git a/src/network.c b/src/network.c index b5f3d489..613caa73 100644 --- a/src/network.c +++ b/src/network.c @@ -27,8 +27,8 @@ #include "collectd.h" -#include "common.h" #include "plugin.h" +#include "utils/common/common.h" #include "utils_cache.h" #include "utils_complain.h" #include "utils_fbhash.h" @@ -113,6 +113,7 @@ struct sockent_client { #endif cdtime_t next_resolve_reconnect; cdtime_t resolve_interval; + struct sockaddr_storage *bind_addr; }; struct sockent_server { @@ -141,6 +142,7 @@ typedef struct sockent { } data; struct sockent *next; + pthread_mutex_t lock; } sockent_t; /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 @@ -261,30 +263,30 @@ typedef struct receive_list_entry_s receive_list_entry_t; /* * Private variables */ -static int network_config_ttl = 0; +static int network_config_ttl; /* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */ static size_t network_config_packet_size = 1452; -static _Bool network_config_forward = 0; -static _Bool network_config_stats = 0; +static bool network_config_forward; +static bool network_config_stats; -static sockent_t *sending_sockets = NULL; +static sockent_t *sending_sockets; -static receive_list_entry_t *receive_list_head = NULL; -static receive_list_entry_t *receive_list_tail = NULL; +static receive_list_entry_t *receive_list_head; +static receive_list_entry_t *receive_list_tail; static pthread_mutex_t receive_list_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t receive_list_cond = PTHREAD_COND_INITIALIZER; -static uint64_t receive_list_length = 0; +static uint64_t receive_list_length; -static sockent_t *listen_sockets = NULL; -static struct pollfd *listen_sockets_pollfd = NULL; -static size_t listen_sockets_num = 0; +static sockent_t *listen_sockets; +static struct pollfd *listen_sockets_pollfd; +static size_t listen_sockets_num; /* The receive and dispatch threads will run as long as `listen_loop' is set to * zero. */ -static int listen_loop = 0; -static int receive_thread_running = 0; +static int listen_loop; +static int receive_thread_running; static pthread_t receive_thread_id; -static int dispatch_thread_running = 0; +static int dispatch_thread_running; static pthread_t dispatch_thread_id; /* Buffer in which to-be-sent network packets are constructed. */ @@ -301,20 +303,20 @@ 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 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 derive_t stats_octets_rx; +static derive_t stats_octets_tx; +static derive_t stats_packets_rx; +static derive_t stats_packets_tx; +static derive_t stats_values_dispatched; +static derive_t stats_values_not_dispatched; +static derive_t stats_values_sent; +static derive_t stats_values_not_sent; static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER; /* * Private functions */ -static _Bool check_receive_okay(const value_list_t *vl) /* {{{ */ +static bool check_receive_okay(const value_list_t *vl) /* {{{ */ { uint64_t time_sent = 0; int status; @@ -324,54 +326,54 @@ static _Bool check_receive_okay(const value_list_t *vl) /* {{{ */ /* This is a value we already sent. Don't allow it to be received again in * order to avoid looping. */ if ((status == 0) && (time_sent >= ((uint64_t)vl->time))) - return (0); + return 0; - return (1); -} /* }}} _Bool check_receive_okay */ + return 1; +} /* }}} bool check_receive_okay */ -static _Bool check_send_okay(const value_list_t *vl) /* {{{ */ +static bool check_send_okay(const value_list_t *vl) /* {{{ */ { - _Bool received = 0; + bool received = 0; int status; if (network_config_forward) - return (1); + return 1; if (vl->meta == NULL) - return (1); + return 1; status = meta_data_get_boolean(vl->meta, "network:received", &received); if (status == -ENOENT) - return (1); + return 1; else if (status != 0) { ERROR("network plugin: check_send_okay: meta_data_get_boolean failed " "with status %i.", status); - return (1); + return 1; } /* By default, only *send* value lists that were not *received* by the * network plugin. */ - return (!received); -} /* }}} _Bool check_send_okay */ + return !received; +} /* }}} bool check_send_okay */ -static _Bool check_notify_received(const notification_t *n) /* {{{ */ +static bool check_notify_received(const notification_t *n) /* {{{ */ { for (notification_meta_t *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 (bool)ptr->nm_value.nm_boolean; - return (0); -} /* }}} _Bool check_notify_received */ + return 0; +} /* }}} bool check_notify_received */ -static _Bool check_send_notify_okay(const notification_t *n) /* {{{ */ +static bool check_send_notify_okay(const notification_t *n) /* {{{ */ { static c_complain_t complain_forwarding = C_COMPLAIN_INIT_STATIC; - _Bool received = 0; + bool received = 0; if (n->meta == NULL) - return (1); + return 1; received = check_notify_received(n); @@ -380,15 +382,15 @@ static _Bool check_send_notify_okay(const notification_t *n) /* {{{ */ LOG_ERR, &complain_forwarding, "network plugin: A notification has been received via the network " "and forwarding is enabled. Forwarding of notifications is currently " - "not supported, because there is not loop-deteciton available. " + "not supported, because there is not loop-detection 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 */ + return !received; +} /* }}} bool check_send_notify_okay */ static int network_dispatch_values(value_list_t *vl, /* {{{ */ const char *username) { @@ -396,19 +398,19 @@ static int network_dispatch_values(value_list_t *vl, /* {{{ */ if ((vl->time == 0) || (strlen(vl->host) == 0) || (strlen(vl->plugin) == 0) || (strlen(vl->type) == 0)) - return (-EINVAL); + return -EINVAL; if (!check_receive_okay(vl)) { #if COLLECT_DEBUG char name[6 * DATA_MAX_NAME_LEN]; FORMAT_VL(name, sizeof(name), vl); - name[sizeof(name) - 1] = 0; + name[sizeof(name) - 1] = '\0'; DEBUG("network plugin: network_dispatch_values: " "NOT dispatching %s.", name); #endif stats_values_not_dispatched++; - return (0); + return 0; } assert(vl->meta == NULL); @@ -416,7 +418,7 @@ static int network_dispatch_values(value_list_t *vl, /* {{{ */ vl->meta = meta_data_create(); if (vl->meta == NULL) { ERROR("network plugin: meta_data_create failed."); - return (-ENOMEM); + return -ENOMEM; } status = meta_data_add_boolean(vl->meta, "network:received", 1); @@ -424,7 +426,7 @@ static int network_dispatch_values(value_list_t *vl, /* {{{ */ ERROR("network plugin: meta_data_add_boolean failed."); meta_data_destroy(vl->meta); vl->meta = NULL; - return (status); + return status; } if (username != NULL) { @@ -433,7 +435,7 @@ static int network_dispatch_values(value_list_t *vl, /* {{{ */ ERROR("network plugin: meta_data_add_string failed."); meta_data_destroy(vl->meta); vl->meta = NULL; - return (status); + return status; } } @@ -443,7 +445,7 @@ static int network_dispatch_values(value_list_t *vl, /* {{{ */ meta_data_destroy(vl->meta); vl->meta = NULL; - return (0); + return 0; } /* }}} int network_dispatch_values */ static int network_dispatch_notification(notification_t *n) /* {{{ */ @@ -457,7 +459,7 @@ static int network_dispatch_notification(notification_t *n) /* {{{ */ ERROR("network plugin: plugin_notification_meta_add_boolean failed."); plugin_notification_meta_free(n->meta); n->meta = NULL; - return (status); + return status; } status = plugin_dispatch_notification(n); @@ -465,7 +467,7 @@ static int network_dispatch_notification(notification_t *n) /* {{{ */ plugin_notification_meta_free(n->meta); n->meta = NULL; - return (status); + return status; } /* }}} int network_dispatch_notification */ #if HAVE_GCRYPT_H @@ -477,7 +479,7 @@ static int network_init_gcrypt(void) /* {{{ */ * Because you can't know in a library whether another library has * already initialized the library */ if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P)) - return (0); + return 0; /* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS @@ -491,7 +493,7 @@ static int network_init_gcrypt(void) /* {{{ */ if (err) { ERROR("network plugin: gcry_control (GCRYCTL_SET_THREAD_CBS) failed: %s", gcry_strerror(err)); - return (-1); + return -1; } #endif @@ -501,11 +503,11 @@ static int network_init_gcrypt(void) /* {{{ */ if (err) { ERROR("network plugin: gcry_control (GCRYCTL_INIT_SECMEM) failed: %s", gcry_strerror(err)); - return (-1); + return -1; } gcry_control(GCRYCTL_INITIALIZATION_FINISHED); - return (0); + return 0; } /* }}} int network_init_gcrypt */ static gcry_cipher_hd_t network_get_aes256_cypher(sockent_t *se, /* {{{ */ @@ -525,11 +527,11 @@ static gcry_cipher_hd_t network_get_aes256_cypher(sockent_t *se, /* {{{ */ cyper_ptr = &se->data.server.cypher; if (username == NULL) - return (NULL); + return NULL; secret = fbh_get(se->data.server.userdb, username); if (secret == NULL) - return (NULL); + return NULL; gcry_md_hash_buffer(GCRY_MD_SHA256, password_hash, secret, strlen(secret)); @@ -543,7 +545,7 @@ static gcry_cipher_hd_t network_get_aes256_cypher(sockent_t *se, /* {{{ */ ERROR("network plugin: gcry_cipher_open returned: %s", gcry_strerror(err)); *cyper_ptr = NULL; - return (NULL); + return NULL; } } else { gcry_cipher_reset(*cyper_ptr); @@ -556,7 +558,7 @@ static gcry_cipher_hd_t network_get_aes256_cypher(sockent_t *se, /* {{{ */ gcry_strerror(err)); gcry_cipher_close(*cyper_ptr); *cyper_ptr = NULL; - return (NULL); + return NULL; } err = gcry_cipher_setiv(*cyper_ptr, iv, iv_size); @@ -565,10 +567,10 @@ static gcry_cipher_hd_t network_get_aes256_cypher(sockent_t *se, /* {{{ */ gcry_strerror(err)); gcry_cipher_close(*cyper_ptr); *cyper_ptr = NULL; - return (NULL); + return NULL; } - return (*cyper_ptr); + return *cyper_ptr; } /* }}} int network_get_aes256_cypher */ #endif /* HAVE_GCRYPT_H */ @@ -590,19 +592,19 @@ static int write_part_values(char **ret_buffer, size_t *ret_buffer_len, (num_values * sizeof(uint8_t)) + (num_values * sizeof(value_t)); if (*ret_buffer_len < packet_len) - return (-1); + return -1; pkg_values_types = malloc(num_values * sizeof(*pkg_values_types)); if (pkg_values_types == NULL) { ERROR("network plugin: write_part_values: malloc failed."); - return (-1); + return -1; } pkg_values = malloc(num_values * sizeof(*pkg_values)); if (pkg_values == NULL) { free(pkg_values_types); ERROR("network plugin: write_part_values: malloc failed."); - return (-1); + return -1; } pkg_ph.type = htons(TYPE_VALUES); @@ -635,7 +637,7 @@ static int write_part_values(char **ret_buffer, size_t *ret_buffer_len, ERROR("network plugin: write_part_values: " "Unknown data source type: %i", ds->ds[i].type); - return (-1); + return -1; } /* switch (ds->ds[i].type) */ } /* for (num_values) */ @@ -663,7 +665,7 @@ static int write_part_values(char **ret_buffer, size_t *ret_buffer_len, free(pkg_values_types); free(pkg_values); - return (0); + return 0; } /* int write_part_values */ static int write_part_number(char **ret_buffer, size_t *ret_buffer_len, @@ -679,7 +681,7 @@ static int write_part_number(char **ret_buffer, size_t *ret_buffer_len, packet_len = sizeof(pkg_head) + sizeof(pkg_value); if (*ret_buffer_len < packet_len) - return (-1); + return -1; pkg_head.type = htons(type); pkg_head.length = htons(packet_len); @@ -697,7 +699,7 @@ static int write_part_number(char **ret_buffer, size_t *ret_buffer_len, *ret_buffer = packet_ptr + packet_len; *ret_buffer_len -= packet_len; - return (0); + return 0; } /* int write_part_number */ static int write_part_string(char **ret_buffer, size_t *ret_buffer_len, @@ -712,7 +714,7 @@ static int write_part_string(char **ret_buffer, size_t *ret_buffer_len, buffer_len = 2 * sizeof(uint16_t) + str_len + 1; if (*ret_buffer_len < buffer_len) - return (-1); + return -1; pkg_type = htons(type); pkg_length = htons(buffer_len); @@ -733,7 +735,7 @@ static int write_part_string(char **ret_buffer, size_t *ret_buffer_len, *ret_buffer = buffer + buffer_len; *ret_buffer_len -= buffer_len; - return (0); + return 0; } /* int write_part_string */ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, @@ -753,9 +755,9 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, if (buffer_len < 15) { NOTICE("network plugin: packet is too short: " - "buffer_len = %zu", + "buffer_len = %" PRIsz, buffer_len); - return (-1); + return -1; } memcpy((void *)&tmp16, buffer, sizeof(tmp16)); @@ -777,10 +779,10 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, if (buffer_len < exp_size) { WARNING("network plugin: parse_part_values: " "Packet too short: " - "Chunk of size %zu expected, " - "but buffer has only %zu bytes left.", + "Chunk of size %" PRIsz " expected, " + "but buffer has only %" PRIsz " bytes left.", exp_size, buffer_len); - return (-1); + return -1; } assert(pkg_numval <= ((buffer_len - 6) / 9)); @@ -788,7 +790,7 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, WARNING("network plugin: parse_part_values: " "Length and number of values " "in the packet don't match."); - return (-1); + return -1; } pkg_types = calloc(pkg_numval, sizeof(*pkg_types)); @@ -797,7 +799,7 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, sfree(pkg_types); sfree(pkg_values); ERROR("network plugin: parse_part_values: calloc failed."); - return (-1); + return -1; } memcpy(pkg_types, buffer, pkg_numval * sizeof(*pkg_types)); @@ -829,7 +831,7 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, pkg_types[i]); sfree(pkg_types); sfree(pkg_values); - return (-1); + return -1; } /* switch (pkg_types[i]) */ } @@ -840,7 +842,7 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len, sfree(pkg_types); - return (0); + return 0; } /* int parse_part_values */ static int parse_part_number(void **ret_buffer, size_t *ret_buffer_len, @@ -857,10 +859,10 @@ static int parse_part_number(void **ret_buffer, size_t *ret_buffer_len, if (buffer_len < exp_size) { WARNING("network plugin: parse_part_number: " "Packet too short: " - "Chunk of size %zu expected, " - "but buffer has only %zu bytes left.", + "Chunk of size %" PRIsz " expected, " + "but buffer has only %" PRIsz " bytes left.", exp_size, buffer_len); - return (-1); + return -1; } memcpy((void *)&tmp16, buffer, sizeof(tmp16)); @@ -878,7 +880,7 @@ static int parse_part_number(void **ret_buffer, size_t *ret_buffer_len, *ret_buffer = buffer; *ret_buffer_len = buffer_len - pkg_length; - return (0); + return 0; } /* int parse_part_number */ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, @@ -893,15 +895,15 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, size_t payload_size; if (output_len == 0) - return (EINVAL); + return EINVAL; if (buffer_len < header_size) { WARNING("network plugin: parse_part_string: " "Packet too short: " - "Chunk of at least size %zu expected, " - "but buffer has only %zu bytes left.", + "Chunk of at least size %" PRIsz " expected, " + "but buffer has only %" PRIsz " bytes left.", header_size, buffer_len); - return (-1); + return -1; } memcpy((void *)&tmp16, buffer, sizeof(tmp16)); @@ -918,9 +920,9 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, WARNING("network plugin: parse_part_string: " "Packet too big: " "Chunk of size %" PRIu16 " received, " - "but buffer has only %zu bytes left.", + "but buffer has only %" PRIsz " bytes left.", pkg_length, buffer_len); - return (-1); + return -1; } /* Check that pkg_length is in the valid range */ @@ -930,7 +932,7 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, "Header claims this packet is only %hu " "bytes long.", pkg_length); - return (-1); + return -1; } /* Check that the package data fits into the output buffer. @@ -939,11 +941,11 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, if (output_len < payload_size) { WARNING("network plugin: parse_part_string: " "Buffer too small: " - "Output buffer holds %zu bytes, " + "Output buffer holds %" PRIsz " bytes, " "which is too small to hold the received " - "%zu byte string.", + "%" PRIsz " byte string.", output_len, payload_size); - return (-1); + return -1; } /* All sanity checks successfull, let's copy the data over */ @@ -956,13 +958,13 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, WARNING("network plugin: parse_part_string: " "Received string does not end " "with a NULL-byte."); - return (-1); + return -1; } *ret_buffer = buffer; *ret_buffer_len = buffer_len - pkg_length; - return (0); + return 0; } /* int parse_part_string */ /* Forward declaration: parse_part_sign_sha256 and parse_part_encr_aes256 call @@ -1005,7 +1007,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ /* Check if the buffer has enough data for this structure. */ if (buffer_len <= PART_SIGNATURE_SHA256_SIZE) - return (-ENOMEM); + return -ENOMEM; /* Read type and length header */ BUFFER_READ(&pss.head.type, sizeof(pss.head.type)); @@ -1016,7 +1018,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ if ((pss_head_length <= PART_SIGNATURE_SHA256_SIZE) || (pss_head_length > buffer_len)) { ERROR("network plugin: HMAC-SHA-256 with invalid length received."); - return (-1); + return -1; } if (se->data.server.userdb == NULL) { @@ -1028,7 +1030,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ *ret_buffer = buffer + pss_head_length; *ret_buffer_len -= pss_head_length; - return (0); + return 0; } /* Copy the hash. */ @@ -1038,7 +1040,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ username_len = pss_head_length - PART_SIGNATURE_SHA256_SIZE; pss.username = malloc(username_len + 1); if (pss.username == NULL) - return (-ENOMEM); + return -ENOMEM; /* Read the username */ BUFFER_READ(pss.username, username_len); @@ -1051,7 +1053,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ if (secret == NULL) { ERROR("network plugin: Unknown user: %s", pss.username); sfree(pss.username); - return (-ENOENT); + return -ENOENT; } /* Create a hash device and check the HMAC */ @@ -1062,7 +1064,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ gcry_strerror(err)); sfree(secret); sfree(pss.username); - return (-1); + return -1; } err = gcry_md_setkey(hd, secret, strlen(secret)); @@ -1071,7 +1073,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ gcry_md_close(hd); sfree(secret); sfree(pss.username); - return (-1); + return -1; } gcry_md_write(hd, buffer + PART_SIGNATURE_SHA256_SIZE, @@ -1082,7 +1084,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ gcry_md_close(hd); sfree(secret); sfree(pss.username); - return (-1); + return -1; } memcpy(hash, hash_ptr, sizeof(hash)); @@ -1105,15 +1107,15 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ *ret_buffer = buffer + buffer_len; *ret_buffer_len = 0; - return (0); + return 0; } /* }}} int parse_part_sign_sha256 */ -/* #endif HAVE_GCRYPT_H */ + /* #endif HAVE_GCRYPT_H */ #else /* if !HAVE_GCRYPT_H */ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_size, int flags) { - static int warning_has_been_printed = 0; + static int warning_has_been_printed; char *buffer; size_t buffer_size; @@ -1127,14 +1129,14 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ buffer_offset = 0; if (buffer_size <= PART_SIGNATURE_SHA256_SIZE) - return (-ENOMEM); + return -ENOMEM; BUFFER_READ(&pss.head.type, sizeof(pss.head.type)); BUFFER_READ(&pss.head.length, sizeof(pss.head.length)); part_len = ntohs(pss.head.length); if ((part_len <= PART_SIGNATURE_SHA256_SIZE) || (part_len > buffer_size)) - return (-EINVAL); + return -EINVAL; if (warning_has_been_printed == 0) { WARNING("network plugin: Received signed packet, but the network " @@ -1149,7 +1151,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ *ret_buffer = buffer + buffer_size; *ret_buffer_size = 0; - return (0); + return 0; } /* }}} int parse_part_sign_sha256 */ #endif /* !HAVE_GCRYPT_H */ @@ -1173,7 +1175,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ if (buffer_len <= PART_ENCRYPTION_AES256_SIZE) { NOTICE("network plugin: parse_part_encr_aes256: " "Discarding short packet."); - return (-1); + return -1; } buffer_offset = 0; @@ -1187,7 +1189,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ if ((part_size <= PART_ENCRYPTION_AES256_SIZE) || (part_size > buffer_len)) { NOTICE("network plugin: parse_part_encr_aes256: " "Discarding part with invalid size."); - return (-1); + return -1; } /* Read the username */ @@ -1198,13 +1200,13 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ (username_len > (part_size - (PART_ENCRYPTION_AES256_SIZE + 1)))) { NOTICE("network plugin: parse_part_encr_aes256: " "Discarding part with invalid username length."); - return (-1); + return -1; } assert(username_len > 0); pea.username = malloc(username_len + 1); if (pea.username == NULL) - return (-ENOMEM); + return -ENOMEM; BUFFER_READ(pea.username, username_len); pea.username[username_len] = 0; @@ -1219,7 +1221,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ if (cypher == NULL) { ERROR("network plugin: Failed to get cypher. Username: %s", pea.username); sfree(pea.username); - return (-1); + return -1; } payload_len = part_size - (PART_ENCRYPTION_AES256_SIZE + username_len); @@ -1230,10 +1232,10 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ part_size - buffer_offset, /* in = */ NULL, /* in len = */ 0); if (err != 0) { - sfree(pea.username); ERROR("network plugin: gcry_cipher_decrypt returned: %s. Username: %s", gcry_strerror(err), pea.username); - return (-1); + sfree(pea.username); + return -1; } /* Read the hash */ @@ -1248,29 +1250,27 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ if (memcmp(hash, pea.hash, sizeof(hash)) != 0) { ERROR("network plugin: Checksum mismatch. Username: %s", pea.username); sfree(pea.username); - return (-1); + return -1; } parse_packet(se, buffer + buffer_offset, payload_len, flags | PP_ENCRYPTED, pea.username); - /* XXX: Free pea.username?!? */ - /* Update return values */ *ret_buffer = buffer + part_size; *ret_buffer_len = buffer_len - part_size; sfree(pea.username); - return (0); + return 0; } /* }}} int parse_part_encr_aes256 */ -/* #endif HAVE_GCRYPT_H */ + /* #endif HAVE_GCRYPT_H */ #else /* if !HAVE_GCRYPT_H */ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_size, int flags) { - static int warning_has_been_printed = 0; + static int warning_has_been_printed; char *buffer; size_t buffer_size; @@ -1293,7 +1293,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ if ((ph_length <= PART_ENCRYPTION_AES256_SIZE) || (ph_length > buffer_size)) { ERROR("network plugin: AES-256 encrypted part " "with invalid length received."); - return (-1); + return -1; } if (warning_has_been_printed == 0) { @@ -1306,7 +1306,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ *ret_buffer = (void *)(((char *)*ret_buffer) + ph_length); *ret_buffer_size -= ph_length; - return (0); + return 0; } /* }}} int parse_part_encr_aes256 */ #endif /* !HAVE_GCRYPT_H */ @@ -1493,7 +1493,7 @@ static int parse_packet(sockent_t *se, /* {{{ */ WARNING("network plugin: parse_packet: Received truncated " "packet, try increasing `MaxPacketSize'"); - return (status); + return status; } /* }}} int parse_packet */ static void free_sockent_client(struct sockent_client *sec) /* {{{ */ @@ -1503,6 +1503,7 @@ static void free_sockent_client(struct sockent_client *sec) /* {{{ */ sec->fd = -1; } sfree(sec->addr); + sfree(sec->bind_addr); #if HAVE_GCRYPT_H sfree(sec->username); sfree(sec->password); @@ -1540,6 +1541,7 @@ static void sockent_destroy(sockent_t *se) /* {{{ */ sfree(se->node); sfree(se->service); + pthread_mutex_destroy(&se->lock); if (se->type == SOCKENT_TYPE_CLIENT) free_sockent_client(&se->data.client); @@ -1567,7 +1569,7 @@ static int network_set_ttl(const sockent_t *se, const struct addrinfo *ai) { assert(se->type == SOCKENT_TYPE_CLIENT); if ((network_config_ttl < 1) || (network_config_ttl > 255)) - return (-1); + return -1; if (ai->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)ai->ai_addr; @@ -1580,10 +1582,8 @@ static int network_set_ttl(const sockent_t *se, const struct addrinfo *ai) { if (setsockopt(se->data.client.fd, IPPROTO_IP, optname, &network_config_ttl, sizeof(network_config_ttl)) != 0) { - char errbuf[1024]; - ERROR("network plugin: setsockopt (ipv4-ttl): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (ipv4-ttl): %s", STRERRNO); + return -1; } } else if (ai->ai_family == AF_INET6) { /* Useful example: @@ -1598,14 +1598,12 @@ static int network_set_ttl(const sockent_t *se, const struct addrinfo *ai) { if (setsockopt(se->data.client.fd, IPPROTO_IPV6, optname, &network_config_ttl, sizeof(network_config_ttl)) != 0) { - char errbuf[1024]; - ERROR("network plugin: setsockopt(ipv6-ttl): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt(ipv6-ttl): %s", STRERRNO); + return -1; } } - return (0); + return 0; } /* int network_set_ttl */ static int network_set_interface(const sockent_t *se, @@ -1636,13 +1634,11 @@ static int network_set_interface(const sockent_t *se, if (setsockopt(se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) != 0) { - char errbuf[1024]; - ERROR("network plugin: setsockopt (ipv4-multicast-if): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (ipv4-multicast-if): %s", STRERRNO); + return -1; } - return (0); + return 0; } } else if (ai->ai_family == AF_INET6) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ai->ai_addr; @@ -1650,13 +1646,11 @@ static int network_set_interface(const sockent_t *se, 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("network plugin: setsockopt (ipv6-multicast-if): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (ipv6-multicast-if): %s", STRERRNO); + return -1; } - return (0); + return 0; } } @@ -1667,18 +1661,16 @@ static int network_set_interface(const sockent_t *se, char interface_name[IFNAMSIZ]; if (if_indextoname(se->interface, interface_name) == NULL) - return (-1); + 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("network plugin: setsockopt (bind-if): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (bind-if): %s", STRERRNO); + return -1; } -/* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */ + /* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */ #else WARNING("network plugin: Cannot set the interface on a unicast " @@ -1692,9 +1684,45 @@ static int network_set_interface(const sockent_t *se, #endif } - return (0); + return 0; } /* }}} network_set_interface */ +static int network_bind_socket_to_addr(sockent_t *se, + const struct addrinfo *ai) { + + if (se->data.client.bind_addr == NULL) + return 0; + + DEBUG("network_plugin: fd %i: bind socket to address", se->data.client.fd); + char pbuffer[64]; + + if (ai->ai_family == AF_INET) { + struct sockaddr_in *addr = + (struct sockaddr_in *)(se->data.client.bind_addr); + inet_ntop(AF_INET, &(addr->sin_addr), pbuffer, 64); + DEBUG("network_plugin: binding client socket to ipv4 address: %s", pbuffer); + if (bind(se->data.client.fd, (struct sockaddr *)addr, sizeof(*addr)) == + -1) { + ERROR("network plugin: failed to bind client socket (ipv4) to %s: %s", + pbuffer, STRERRNO); + return -1; + } + } else if (ai->ai_family == AF_INET6) { + struct sockaddr_in6 *addr = + (struct sockaddr_in6 *)(se->data.client.bind_addr); + inet_ntop(AF_INET6, &(addr->sin6_addr), pbuffer, 64); + DEBUG("network_plugin: binding client socket to ipv6 address: %s", pbuffer); + if (bind(se->data.client.fd, (struct sockaddr *)addr, sizeof(*addr)) == + -1) { + ERROR("network plugin: failed to bind client socket (ipv6) to %s: %s", + pbuffer, STRERRNO); + return -1; + } + } + + return 0; +} /* int network_bind_socket_to_addr */ + static int network_bind_socket(int fd, const struct addrinfo *ai, const int interface_idx) { #if KERNEL_SOLARIS @@ -1702,22 +1730,18 @@ static int network_bind_socket(int fd, const struct addrinfo *ai, #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("network plugin: setsockopt (reuseaddr): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) == -1) { + ERROR("network plugin: setsockopt (reuseaddr): %s", STRERRNO); + return -1; } DEBUG("fd = %i; calling `bind'", fd); if (bind(fd, ai->ai_addr, ai->ai_addrlen) == -1) { - char errbuf[1024]; - ERROR("bind: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("bind: %s", STRERRNO); + return -1; } if (ai->ai_family == AF_INET) { @@ -1744,21 +1768,17 @@ static int network_bind_socket(int fd, const struct addrinfo *ai, if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) == -1) { - char errbuf[1024]; - ERROR("network plugin: setsockopt (multicast-loop): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (multicast-loop): %s", STRERRNO); + return -1; } if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { - char errbuf[1024]; - ERROR("network plugin: setsockopt (add-membership): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (add-membership): %s", STRERRNO); + return -1; } - return (0); + return 0; } } else if (ai->ai_family == AF_INET6) { /* Useful example: @@ -1784,21 +1804,17 @@ static int network_bind_socket(int fd, const struct addrinfo *ai, if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) == -1) { - char errbuf[1024]; - ERROR("network plugin: setsockopt (ipv6-multicast-loop): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (ipv6-multicast-loop): %s", STRERRNO); + return -1; } if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { - char errbuf[1024]; - ERROR("network plugin: setsockopt (ipv6-add-membership): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (ipv6-add-membership): %s", STRERRNO); + return -1; } - return (0); + return 0; } } @@ -1811,21 +1827,19 @@ static int network_bind_socket(int fd, const struct addrinfo *ai, char interface_name[IFNAMSIZ]; if (if_indextoname(interface_idx, interface_name) == NULL) - return (-1); + 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("network plugin: setsockopt (bind-if): %s", - sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + ERROR("network plugin: setsockopt (bind-if): %s", STRERRNO); + return -1; } } #endif /* HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */ - return (0); + return 0; } /* int network_bind_socket */ /* Initialize a sockent structure. `type' must be either `SOCKENT_TYPE_CLIENT' @@ -1835,17 +1849,18 @@ static sockent_t *sockent_create(int type) /* {{{ */ sockent_t *se; if ((type != SOCKENT_TYPE_CLIENT) && (type != SOCKENT_TYPE_SERVER)) - return (NULL); + return NULL; se = calloc(1, sizeof(*se)); if (se == NULL) - return (NULL); + return NULL; se->type = type; se->node = NULL; se->service = NULL; se->interface = 0; se->next = NULL; + pthread_mutex_init(&se->lock, NULL); if (type == SOCKENT_TYPE_SERVER) { se->data.server.fd = NULL; @@ -1859,6 +1874,7 @@ static sockent_t *sockent_create(int type) /* {{{ */ } else { se->data.client.fd = -1; se->data.client.addr = NULL; + se->data.client.bind_addr = NULL; se->data.client.resolve_interval = 0; se->data.client.next_resolve_reconnect = 0; #if HAVE_GCRYPT_H @@ -1869,7 +1885,7 @@ static sockent_t *sockent_create(int type) /* {{{ */ #endif } - return (se); + return se; } /* }}} sockent_t *sockent_create */ static int sockent_init_crypto(sockent_t *se) /* {{{ */ @@ -1880,7 +1896,7 @@ static int sockent_init_crypto(sockent_t *se) /* {{{ */ if (network_init_gcrypt() < 0) { ERROR("network plugin: Cannot configure client socket with " "security: Failed to initialize crypto library."); - return (-1); + return -1; } if ((se->data.client.username == NULL) || @@ -1888,7 +1904,7 @@ static int sockent_init_crypto(sockent_t *se) /* {{{ */ ERROR("network plugin: Client socket with " "security requested, but no " "credentials are configured."); - return (-1); + return -1; } gcry_md_hash_buffer(GCRY_MD_SHA256, se->data.client.password_hash, se->data.client.password, @@ -1900,26 +1916,26 @@ static int sockent_init_crypto(sockent_t *se) /* {{{ */ (se->data.server.auth_file == NULL)) { ERROR("network plugin: Server socket with security requested, " "but no \"AuthFile\" is configured."); - return (-1); + return -1; } if (se->data.server.auth_file != NULL) { if (network_init_gcrypt() < 0) { ERROR("network plugin: Cannot configure server socket with security: " "Failed to initialize crypto library."); - return (-1); + return -1; } se->data.server.userdb = fbh_create(se->data.server.auth_file); if (se->data.server.userdb == NULL) { ERROR("network plugin: Reading password file \"%s\" failed.", se->data.server.auth_file); - return (-1); + return -1; } } } #endif /* }}} HAVE_GCRYPT_H */ - return (0); + return 0; } /* }}} int sockent_init_crypto */ static int sockent_client_disconnect(sockent_t *se) /* {{{ */ @@ -1927,7 +1943,7 @@ static int sockent_client_disconnect(sockent_t *se) /* {{{ */ struct sockent_client *client; if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT)) - return (EINVAL); + return EINVAL; client = &se->data.client; if (client->fd >= 0) /* connected */ @@ -1936,10 +1952,12 @@ static int sockent_client_disconnect(sockent_t *se) /* {{{ */ client->fd = -1; } + DEBUG("network plugin: free (se = %p, addr = %p);", (void *)se, + (void *)client->addr); sfree(client->addr); client->addrlen = 0; - return (0); + return 0; } /* }}} int sockent_client_disconnect */ static int sockent_client_connect(sockent_t *se) /* {{{ */ @@ -1949,11 +1967,11 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ struct sockent_client *client; struct addrinfo *ai_list; int status; - _Bool reconnect = 0; + bool reconnect = false; cdtime_t now; if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT)) - return (EINVAL); + return EINVAL; client = &se->data.client; @@ -1963,11 +1981,11 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ "next_resolve_reconnect = %lf", CDTIME_T_TO_DOUBLE(client->resolve_interval), CDTIME_T_TO_DOUBLE(client->next_resolve_reconnect)); - reconnect = 1; + reconnect = true; } if (client->fd >= 0 && !reconnect) /* already connected and not stale*/ - return (0); + return 0; struct addrinfo ai_hints = {.ai_family = AF_UNSPEC, .ai_flags = AI_ADDRCONFIG, @@ -1982,7 +2000,7 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ LOG_ERR, &complaint, "network plugin: getaddrinfo (%s, %s) failed: %s", (se->node == NULL) ? "(null)" : se->node, (se->service == NULL) ? "(null)" : se->service, gai_strerror(status)); - return (-1); + return -1; } else { c_release(LOG_NOTICE, &complaint, "network plugin: Successfully resolved \"%s\".", se->node); @@ -1996,9 +2014,7 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ client->fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (client->fd < 0) { - char errbuf[1024]; - ERROR("network plugin: socket(2) failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("network plugin: socket(2) failed: %s", STRERRNO); continue; } @@ -2009,6 +2025,8 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ client->fd = -1; continue; } + DEBUG("network plugin: alloc (se = %p, addr = %p);", (void *)se, + (void *)client->addr); assert(sizeof(*client->addr) >= ai_ptr->ai_addrlen); memcpy(client->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen); @@ -2016,6 +2034,7 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ network_set_ttl(se, ai_ptr); network_set_interface(se, ai_ptr); + network_bind_socket_to_addr(se, ai_ptr); /* We don't open more than one write-socket per * node/service pair.. */ @@ -2024,11 +2043,11 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ freeaddrinfo(ai_list); if (client->fd < 0) - return (-1); + return -1; if (client->resolve_interval > 0) client->next_resolve_reconnect = now + client->resolve_interval; - return (0); + return 0; } /* }}} int sockent_client_connect */ /* Open the file descriptors for a initialized sockent structure. */ @@ -2041,7 +2060,7 @@ static int sockent_server_listen(sockent_t *se) /* {{{ */ const char *service; if (se == NULL) - return (-1); + return -1; assert(se->data.server.fd == NULL); assert(se->data.server.fd_num == 0); @@ -2065,7 +2084,7 @@ static int sockent_server_listen(sockent_t *se) /* {{{ */ ERROR("network plugin: getaddrinfo (%s, %s) failed: %s", (se->node == NULL) ? "(null)" : se->node, (se->service == NULL) ? "(null)" : se->service, gai_strerror(status)); - return (-1); + return -1; } for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; @@ -2083,9 +2102,7 @@ static int sockent_server_listen(sockent_t *se) /* {{{ */ *tmp = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (*tmp < 0) { - char errbuf[1024]; - ERROR("network plugin: socket(2) failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("network plugin: socket(2) failed: %s", STRERRNO); continue; } @@ -2103,8 +2120,8 @@ static int sockent_server_listen(sockent_t *se) /* {{{ */ freeaddrinfo(ai_list); if (se->data.server.fd_num == 0) - return (-1); - return (0); + return -1; + return 0; } /* }}} int sockent_server_listen */ /* Add a sockent to the global list of sockets */ @@ -2113,7 +2130,7 @@ static int sockent_add(sockent_t *se) /* {{{ */ sockent_t *last_ptr; if (se == NULL) - return (-1); + return -1; if (se->type == SOCKENT_TYPE_SERVER) { struct pollfd *tmp; @@ -2122,7 +2139,7 @@ static int sockent_add(sockent_t *se) /* {{{ */ sizeof(*tmp) * (listen_sockets_num + se->data.server.fd_num)); if (tmp == NULL) { ERROR("network plugin: realloc failed."); - return (-1); + return -1; } listen_sockets_pollfd = tmp; tmp = listen_sockets_pollfd + listen_sockets_num; @@ -2138,14 +2155,14 @@ static int sockent_add(sockent_t *se) /* {{{ */ if (listen_sockets == NULL) { listen_sockets = se; - return (0); + return 0; } last_ptr = listen_sockets; } else /* if (se->type == SOCKENT_TYPE_CLIENT) */ { if (sending_sockets == NULL) { sending_sockets = se; - return (0); + return 0; } last_ptr = sending_sockets; } @@ -2154,7 +2171,7 @@ static int sockent_add(sockent_t *se) /* {{{ */ last_ptr = last_ptr->next; last_ptr->next = se; - return (0); + return 0; } /* }}} int sockent_add */ static void *dispatch_thread(void __attribute__((unused)) * arg) /* {{{ */ @@ -2210,7 +2227,7 @@ static void *dispatch_thread(void __attribute__((unused)) * arg) /* {{{ */ sfree(ent); } /* while (42) */ - return (NULL); + return NULL; } /* }}} void *dispatch_thread */ static int network_receive(void) /* {{{ */ @@ -2233,11 +2250,9 @@ static int network_receive(void) /* {{{ */ while (listen_loop == 0) { status = poll(listen_sockets_pollfd, listen_sockets_num, -1); if (status <= 0) { - char errbuf[1024]; if (errno == EINTR) continue; - ERROR("network plugin: poll(2) failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("network plugin: poll(2) failed: %s", STRERRNO); break; } @@ -2251,10 +2266,8 @@ static int network_receive(void) /* {{{ */ buffer_len = recv(listen_sockets_pollfd[i].fd, buffer, sizeof(buffer), 0 /* no flags */); if (buffer_len < 0) { - char errbuf[1024]; status = (errno != 0) ? errno : -1; - ERROR("network plugin: recv(2) failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("network plugin: recv(2) failed: %s", STRERRNO); break; } @@ -2335,11 +2348,11 @@ static int network_receive(void) /* {{{ */ pthread_mutex_unlock(&receive_list_lock); } - return (status); + return status; } /* }}} int network_receive */ static void *receive_thread(void __attribute__((unused)) * arg) { - return (network_receive() ? (void *)1 : (void *)0); + return network_receive() ? (void *)1 : (void *)0; } /* void *receive_thread */ static void network_init_buffer(void) { @@ -2364,13 +2377,11 @@ static void network_send_buffer_plain(sockent_t *se, /* {{{ */ /* flags = */ 0, (struct sockaddr *)se->data.client.addr, se->data.client.addrlen); if (status < 0) { - char errbuf[1024]; - if ((errno == EINTR) || (errno == EAGAIN)) continue; ERROR("network plugin: sendto failed: %s. Closing sending socket.", - sstrerror(errno, errbuf, sizeof(errbuf))); + STRERRNO); sockent_client_disconnect(se); return; } @@ -2482,7 +2493,7 @@ static void network_send_buffer_encrypted(sockent_t *se, /* {{{ */ assert(buffer_size <= sizeof(buffer)); DEBUG("network plugin: network_send_buffer_encrypted: " - "buffer_size = %zu;", + "buffer_size = %" PRIsz ";", buffer_size); pea.head.length = htons( @@ -2533,9 +2544,11 @@ static void network_send_buffer_encrypted(sockent_t *se, /* {{{ */ static void network_send_buffer(char *buffer, size_t buffer_len) /* {{{ */ { - DEBUG("network plugin: network_send_buffer: buffer_len = %zu", buffer_len); + DEBUG("network plugin: network_send_buffer: buffer_len = %" PRIsz, + buffer_len); for (sockent_t *se = sending_sockets; se != NULL; se = se->next) { + pthread_mutex_lock(&se->lock); #if HAVE_GCRYPT_H if (se->data.client.security_level == SECURITY_LEVEL_ENCRYPT) network_send_buffer_encrypted(se, buffer, buffer_len); @@ -2544,6 +2557,7 @@ static void network_send_buffer(char *buffer, size_t buffer_len) /* {{{ */ else /* if (se->data.client.security_level == SECURITY_LEVEL_NONE) */ #endif /* HAVE_GCRYPT_H */ network_send_buffer_plain(se, buffer, buffer_len); + pthread_mutex_unlock(&se->lock); } /* for (sending_sockets) */ } /* }}} void network_send_buffer */ @@ -2555,28 +2569,28 @@ static int add_to_buffer(char *buffer, size_t buffer_size, /* {{{ */ if (strcmp(vl_def->host, vl->host) != 0) { if (write_part_string(&buffer, &buffer_size, TYPE_HOST, vl->host, strlen(vl->host)) != 0) - return (-1); + return -1; sstrncpy(vl_def->host, vl->host, sizeof(vl_def->host)); } if (vl_def->time != vl->time) { if (write_part_number(&buffer, &buffer_size, TYPE_TIME_HR, (uint64_t)vl->time)) - return (-1); + return -1; vl_def->time = vl->time; } if (vl_def->interval != vl->interval) { if (write_part_number(&buffer, &buffer_size, TYPE_INTERVAL_HR, (uint64_t)vl->interval)) - return (-1); + return -1; vl_def->interval = vl->interval; } if (strcmp(vl_def->plugin, vl->plugin) != 0) { if (write_part_string(&buffer, &buffer_size, TYPE_PLUGIN, vl->plugin, strlen(vl->plugin)) != 0) - return (-1); + return -1; sstrncpy(vl_def->plugin, vl->plugin, sizeof(vl_def->plugin)); } @@ -2584,7 +2598,7 @@ static int add_to_buffer(char *buffer, size_t buffer_size, /* {{{ */ if (write_part_string(&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE, vl->plugin_instance, strlen(vl->plugin_instance)) != 0) - return (-1); + return -1; sstrncpy(vl_def->plugin_instance, vl->plugin_instance, sizeof(vl_def->plugin_instance)); } @@ -2592,22 +2606,22 @@ static int add_to_buffer(char *buffer, size_t buffer_size, /* {{{ */ if (strcmp(vl_def->type, vl->type) != 0) { if (write_part_string(&buffer, &buffer_size, TYPE_TYPE, vl->type, strlen(vl->type)) != 0) - return (-1); + return -1; sstrncpy(vl_def->type, ds->type, sizeof(vl_def->type)); } if (strcmp(vl_def->type_instance, vl->type_instance) != 0) { if (write_part_string(&buffer, &buffer_size, TYPE_TYPE_INSTANCE, vl->type_instance, strlen(vl->type_instance)) != 0) - return (-1); + 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); + return -1; - return (buffer - buffer_orig); + return buffer - buffer_orig; } /* }}} int add_to_buffer */ static void flush_buffer(void) { @@ -2635,7 +2649,7 @@ static int network_write(const data_set_t *ds, const value_list_t *vl, #if COLLECT_DEBUG char name[6 * DATA_MAX_NAME_LEN]; FORMAT_VL(name, sizeof(name), vl); - name[sizeof(name) - 1] = 0; + name[sizeof(name) - 1] = '\0'; DEBUG("network plugin: network_write: " "NOT sending %s.", name); @@ -2645,17 +2659,17 @@ static int network_write(const data_set_t *ds, const value_list_t *vl, pthread_mutex_lock(&stats_lock); stats_values_not_sent++; pthread_mutex_unlock(&stats_lock); - return (0); + return 0; } uc_meta_data_add_unsigned_int(vl, "network:time_sent", (uint64_t)vl->time); pthread_mutex_lock(&send_buffer_lock); - status = - add_to_buffer(send_buffer_ptr, network_config_packet_size - - (send_buffer_fill + BUFF_SIG_SIZE), - &send_buffer_vl, ds, vl); + status = add_to_buffer(send_buffer_ptr, + network_config_packet_size - + (send_buffer_fill + BUFF_SIG_SIZE), + &send_buffer_vl, ds, vl); if (status >= 0) { /* status == bytes added to the buffer */ send_buffer_fill += status; @@ -2666,10 +2680,10 @@ static int network_write(const data_set_t *ds, const value_list_t *vl, } else { flush_buffer(); - status = - add_to_buffer(send_buffer_ptr, network_config_packet_size - - (send_buffer_fill + BUFF_SIG_SIZE), - &send_buffer_vl, ds, vl); + status = add_to_buffer(send_buffer_ptr, + network_config_packet_size - + (send_buffer_fill + BUFF_SIG_SIZE), + &send_buffer_vl, ds, vl); if (status >= 0) { send_buffer_fill += status; @@ -2688,7 +2702,7 @@ static int network_write(const data_set_t *ds, const value_list_t *vl, pthread_mutex_unlock(&send_buffer_lock); - return ((status < 0) ? -1 : 0); + return (status < 0) ? -1 : 0; } /* int network_write */ static int network_config_set_ttl(const oconfig_item_t *ci) /* {{{ */ @@ -2696,15 +2710,15 @@ static int network_config_set_ttl(const oconfig_item_t *ci) /* {{{ */ int tmp = 0; if (cf_util_get_int(ci, &tmp) != 0) - return (-1); + return -1; else if ((tmp > 0) && (tmp <= 255)) network_config_ttl = tmp; else { WARNING("network plugin: The `TimeToLive' must be between 1 and 255."); - return (-1); + return -1; } - return (0); + return 0; } /* }}} int network_config_set_ttl */ static int network_config_set_interface(const oconfig_item_t *ci, /* {{{ */ @@ -2712,27 +2726,79 @@ static int network_config_set_interface(const oconfig_item_t *ci, /* {{{ */ char if_name[256]; if (cf_util_get_string_buffer(ci, if_name, sizeof(if_name)) != 0) - return (-1); + return -1; *interface = if_nametoindex(if_name); - return (0); + return 0; } /* }}} int network_config_set_interface */ +static int +network_config_set_bind_address(const oconfig_item_t *ci, + struct sockaddr_storage **bind_address) { + if ((*bind_address) != NULL) { + ERROR("network_plugin: only a single bind address is allowed"); + return -1; + } + + char addr_text[256]; + + if (cf_util_get_string_buffer(ci, addr_text, sizeof(addr_text)) != 0) + return -1; + + int ret; + struct addrinfo *res = NULL; + struct addrinfo ai_hints = {.ai_family = AF_UNSPEC, + .ai_flags = AI_NUMERICHOST, + .ai_protocol = IPPROTO_UDP, + .ai_socktype = SOCK_DGRAM}; + + ret = getaddrinfo(addr_text, NULL, &ai_hints, &res); + if (ret) { + ERROR("network plugin: Bind address option has invalid address set: %s", + gai_strerror(ret)); + return -1; + } + + *bind_address = malloc(sizeof(**bind_address)); + if (*bind_address == NULL) { + ERROR("network plugin: network_config_set_bind_address: malloc failed."); + freeaddrinfo(res); + return -1; + } + (*bind_address)->ss_family = res->ai_family; + if (res->ai_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)(*bind_address); + inet_pton(AF_INET, addr_text, &(addr->sin_addr)); + } else if (res->ai_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(*bind_address); + inet_pton(AF_INET6, addr_text, &(addr->sin6_addr)); + } else { + ERROR("network plugin: %s is an unknown address format %d\n", addr_text, + res->ai_family); + sfree(*bind_address); + freeaddrinfo(res); + return -1; + } + + freeaddrinfo(res); + return 0; +} /* int network_config_set_bind_address */ + static int network_config_set_buffer_size(const oconfig_item_t *ci) /* {{{ */ { int tmp = 0; if (cf_util_get_int(ci, &tmp) != 0) - return (-1); + return -1; else if ((tmp >= 1024) && (tmp <= 65535)) network_config_packet_size = tmp; else { WARNING( "network plugin: The `MaxPacketSize' must be between 1024 and 65535."); - return (-1); + return -1; } - return (0); + return 0; } /* }}} int network_config_set_buffer_size */ #if HAVE_GCRYPT_H @@ -2742,7 +2808,7 @@ static int network_config_set_security_level(oconfig_item_t *ci, /* {{{ */ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("network plugin: The `SecurityLevel' config option needs exactly " "one string argument."); - return (-1); + return -1; } str = ci->values[0].value.string; @@ -2754,10 +2820,10 @@ static int network_config_set_security_level(oconfig_item_t *ci, /* {{{ */ *retval = SECURITY_LEVEL_NONE; else { WARNING("network plugin: Unknown security level: %s.", str); - return (-1); + return -1; } - return (0); + return 0; } /* }}} int network_config_set_security_level */ #endif /* HAVE_GCRYPT_H */ @@ -2772,13 +2838,13 @@ static int network_config_add_listen(const oconfig_item_t *ci) /* {{{ */ ERROR("network plugin: The `%s' config option needs " "one or two string arguments.", ci->key); - return (-1); + return -1; } se = sockent_create(SOCKENT_TYPE_SERVER); if (se == NULL) { ERROR("network plugin: sockent_create failed."); - return (-1); + return -1; } se->node = strdup(ci->values[0].value.string); @@ -2809,7 +2875,7 @@ static int network_config_add_listen(const oconfig_item_t *ci) /* {{{ */ "requested, but no AuthFile option was given. Cowardly refusing to " "open this socket!"); sockent_destroy(se); - return (-1); + return -1; } #endif /* HAVE_GCRYPT_H */ @@ -2818,7 +2884,7 @@ static int network_config_add_listen(const oconfig_item_t *ci) /* {{{ */ ERROR("network plugin: network_config_add_listen: sockent_init_crypto() " "failed."); sockent_destroy(se); - return (-1); + return -1; } status = sockent_server_listen(se); @@ -2826,17 +2892,17 @@ static int network_config_add_listen(const oconfig_item_t *ci) /* {{{ */ ERROR("network plugin: network_config_add_listen: sockent_server_listen " "failed."); sockent_destroy(se); - return (-1); + return -1; } status = sockent_add(se); if (status != 0) { ERROR("network plugin: network_config_add_listen: sockent_add failed."); sockent_destroy(se); - return (-1); + return -1; } - return (0); + return 0; } /* }}} int network_config_add_listen */ static int network_config_add_server(const oconfig_item_t *ci) /* {{{ */ @@ -2850,13 +2916,13 @@ static int network_config_add_server(const oconfig_item_t *ci) /* {{{ */ ERROR("network plugin: The `%s' config option needs " "one or two string arguments.", ci->key); - return (-1); + return -1; } se = sockent_create(SOCKENT_TYPE_CLIENT); if (se == NULL) { ERROR("network plugin: sockent_create failed."); - return (-1); + return -1; } se->node = strdup(ci->values[0].value.string); @@ -2877,6 +2943,8 @@ static int network_config_add_server(const oconfig_item_t *ci) /* {{{ */ #endif /* HAVE_GCRYPT_H */ if (strcasecmp("Interface", child->key) == 0) network_config_set_interface(child, &se->interface); + else if (strcasecmp("BindAddress", child->key) == 0) + network_config_set_bind_address(child, &se->data.client.bind_addr); else if (strcasecmp("ResolveInterval", child->key) == 0) cf_util_get_cdtime(child, &se->data.client.resolve_interval); else { @@ -2892,7 +2960,7 @@ static int network_config_add_server(const oconfig_item_t *ci) /* {{{ */ "requested, but no Username or Password option was given. " "Cowardly refusing to open this socket!"); sockent_destroy(se); - return (-1); + return -1; } #endif /* HAVE_GCRYPT_H */ @@ -2901,7 +2969,7 @@ static int network_config_add_server(const oconfig_item_t *ci) /* {{{ */ ERROR("network plugin: network_config_add_server: sockent_init_crypto() " "failed."); sockent_destroy(se); - return (-1); + return -1; } /* No call to sockent_client_connect() here -- it is called from @@ -2911,10 +2979,10 @@ static int network_config_add_server(const oconfig_item_t *ci) /* {{{ */ if (status != 0) { ERROR("network plugin: network_config_add_server: sockent_add failed."); sockent_destroy(se); - return (-1); + return -1; } - return (0); + return 0; } /* }}} int network_config_add_server */ static int network_config(oconfig_item_t *ci) /* {{{ */ @@ -2946,7 +3014,7 @@ static int network_config(oconfig_item_t *ci) /* {{{ */ } } - return (0); + return 0; } /* }}} int network_config */ static int network_notification(const notification_t *n, @@ -2958,63 +3026,63 @@ static int network_notification(const notification_t *n, int status; if (!check_send_notify_okay(n)) - return (0); + return 0; memset(buffer, 0, sizeof(buffer)); status = write_part_number(&buffer_ptr, &buffer_free, TYPE_TIME_HR, (uint64_t)n->time); if (status != 0) - return (-1); + return -1; status = write_part_number(&buffer_ptr, &buffer_free, TYPE_SEVERITY, (uint64_t)n->severity); if (status != 0) - return (-1); + return -1; if (strlen(n->host) > 0) { status = write_part_string(&buffer_ptr, &buffer_free, TYPE_HOST, n->host, strlen(n->host)); if (status != 0) - return (-1); + return -1; } if (strlen(n->plugin) > 0) { status = write_part_string(&buffer_ptr, &buffer_free, TYPE_PLUGIN, n->plugin, strlen(n->plugin)); if (status != 0) - return (-1); + return -1; } if (strlen(n->plugin_instance) > 0) { status = write_part_string(&buffer_ptr, &buffer_free, TYPE_PLUGIN_INSTANCE, n->plugin_instance, strlen(n->plugin_instance)); if (status != 0) - return (-1); + return -1; } if (strlen(n->type) > 0) { status = write_part_string(&buffer_ptr, &buffer_free, TYPE_TYPE, n->type, strlen(n->type)); if (status != 0) - return (-1); + return -1; } if (strlen(n->type_instance) > 0) { status = write_part_string(&buffer_ptr, &buffer_free, TYPE_TYPE_INSTANCE, n->type_instance, strlen(n->type_instance)); if (status != 0) - return (-1); + return -1; } status = write_part_string(&buffer_ptr, &buffer_free, TYPE_MESSAGE, n->message, strlen(n->message)); if (status != 0) - return (-1); + return -1; network_send_buffer(buffer, sizeof(buffer) - buffer_free); - return (0); + return 0; } /* int network_notification */ static int network_shutdown(void) { @@ -3055,7 +3123,7 @@ static int network_shutdown(void) { plugin_unregister_write("network"); plugin_unregister_shutdown("network"); - return (0); + return 0; } /* int network_shutdown */ static int network_stats_read(void) /* {{{ */ @@ -3126,17 +3194,17 @@ static int network_stats_read(void) /* {{{ */ vl.type_instance[0] = 0; plugin_dispatch_values(&vl); - return (0); + return 0; } /* }}} int network_stats_read */ static int network_init(void) { - static _Bool have_init = 0; + static bool have_init; /* Check if we were already initialized. If so, just return - there's * nothing more to do (for now, that is). */ if (have_init) - return (0); - have_init = 1; + return 0; + have_init = true; if (network_config_stats) plugin_register_read("network", network_stats_read); @@ -3146,7 +3214,7 @@ static int network_init(void) { send_buffer = malloc(network_config_packet_size); if (send_buffer == NULL) { ERROR("network plugin: malloc failed."); - return (-1); + return -1; } network_init_buffer(); @@ -3161,7 +3229,7 @@ static int network_init(void) { /* If no threads need to be started, return here. */ if ((listen_sockets_num == 0) || ((dispatch_thread_running != 0) && (receive_thread_running != 0))) - return (0); + return 0; if (dispatch_thread_running == 0) { int status; @@ -3169,9 +3237,7 @@ static int network_init(void) { dispatch_thread, NULL /* no argument */, "network disp"); if (status != 0) { - char errbuf[1024]; - ERROR("network: pthread_create failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("network: pthread_create failed: %s", STRERRNO); } else { dispatch_thread_running = 1; } @@ -3183,15 +3249,13 @@ static int network_init(void) { receive_thread, NULL /* no argument */, "network recv"); if (status != 0) { - char errbuf[1024]; - ERROR("network: pthread_create failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("network: pthread_create failed: %s", STRERRNO); } else { receive_thread_running = 1; } } - return (0); + return 0; } /* int network_init */ /* @@ -3211,14 +3275,14 @@ static int network_flush(cdtime_t timeout, cdtime_t now = cdtime(); if ((send_buffer_last_update + timeout) > now) { pthread_mutex_unlock(&send_buffer_lock); - return (0); + return 0; } } flush_buffer(); } pthread_mutex_unlock(&send_buffer_lock); - return (0); + return 0; } /* int network_flush */ void module_register(void) {