* Aman Gupta <aman at tmm1.net>
**/
+#define _DEFAULT_SOURCE
#define _BSD_SOURCE /* For struct ip_mreq */
#include "collectd.h"
gcry_cipher_hd_t cypher;
unsigned char password_hash[32];
#endif
+ cdtime_t next_resolve_reconnect;
+ cdtime_t resolve_interval;
};
struct sockent_server
} /* int parse_part_number */
static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len,
- char *output, int output_len)
+ char *output, size_t const output_len)
{
char *buffer = *ret_buffer;
size_t buffer_len = *ret_buffer_len;
uint16_t tmp16;
- size_t header_size = 2 * sizeof (uint16_t);
+ size_t const header_size = 2 * sizeof (uint16_t);
uint16_t pkg_length;
+ size_t payload_size;
+
+ if (output_len <= 0)
+ return (EINVAL);
if (buffer_len < header_size)
{
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
pkg_length = ntohs (tmp16);
+ payload_size = ((size_t) pkg_length) - header_size;
/* Check that packet fits in the input buffer */
if (pkg_length > buffer_len)
/* Check that the package data fits into the output buffer.
* The previous if-statement ensures that:
* `pkg_length > header_size' */
- if ((output_len < 0)
- || ((size_t) output_len < ((size_t) pkg_length - header_size)))
+ if (output_len < payload_size)
{
WARNING ("network plugin: parse_part_string: "
- "Output buffer too small.");
+ "Buffer too small: "
+ "Output buffer holds %zu bytes, "
+ "which is too small to hold the received "
+ "%zu byte string.",
+ output_len, payload_size);
return (-1);
}
/* All sanity checks successfull, let's copy the data over */
- output_len = pkg_length - header_size;
- memcpy ((void *) output, (void *) buffer, output_len);
- buffer += output_len;
+ memcpy ((void *) output, (void *) buffer, payload_size);
+ buffer += payload_size;
/* For some very weird reason '\0' doesn't do the trick on SPARC in
* this statement. */
- if (output[output_len - 1] != 0)
+ if (output[payload_size - 1] != 0)
{
WARNING ("network plugin: parse_part_string: "
"Received string does not end "
{
se->data.client.fd = -1;
se->data.client.addr = NULL;
+ se->data.client.resolve_interval = 0;
+ se->data.client.next_resolve_reconnect = 0;
#if HAVE_LIBGCRYPT
se->data.client.security_level = SECURITY_LEVEL_NONE;
se->data.client.username = NULL;
return (0);
} /* }}} int sockent_init_crypto */
+static int sockent_client_disconnect (sockent_t *se) /* {{{ */
+{
+ struct sockent_client *client;
+
+ if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
+ return (EINVAL);
+
+ client = &se->data.client;
+ if (client->fd >= 0) /* connected */
+ {
+ close (client->fd);
+ client->fd = -1;
+ }
+
+ sfree (client->addr);
+ client->addrlen = 0;
+
+ return (0);
+} /* }}} int sockent_client_disconnect */
+
static int sockent_client_connect (sockent_t *se) /* {{{ */
{
static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
struct addrinfo ai_hints;
struct addrinfo *ai_list = NULL, *ai_ptr;
int status;
+ _Bool reconnect = 0;
+ cdtime_t now;
if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
return (EINVAL);
client = &se->data.client;
- if (client->fd >= 0) /* already connected */
+
+ now = cdtime ();
+ if (client->resolve_interval != 0 && client->next_resolve_reconnect < now) {
+ DEBUG("network plugin: Reconnecting socket, resolve_interval = %lf, next_resolve_reconnect = %lf",
+ CDTIME_T_TO_DOUBLE(client->resolve_interval), CDTIME_T_TO_DOUBLE(client->next_resolve_reconnect));
+ reconnect = 1;
+ }
+
+ if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
return (0);
memset (&ai_hints, 0, sizeof (ai_hints));
for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
+ if (client->fd >= 0) /* when we reconnect */
+ sockent_client_disconnect(se);
+
client->fd = socket (ai_ptr->ai_family,
ai_ptr->ai_socktype,
ai_ptr->ai_protocol);
freeaddrinfo (ai_list);
if (client->fd < 0)
return (-1);
- return (0);
-} /* }}} int sockent_client_connect */
-
-static int sockent_client_disconnect (sockent_t *se) /* {{{ */
-{
- struct sockent_client *client;
-
- if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
- return (EINVAL);
-
- client = &se->data.client;
- if (client->fd >= 0) /* connected */
- {
- close (client->fd);
- client->fd = -1;
- }
-
- sfree (client->addr);
- client->addrlen = 0;
+ if (client->resolve_interval > 0)
+ client->next_resolve_reconnect = now + client->resolve_interval;
return (0);
-} /* }}} int sockent_client_disconnect */
+} /* }}} int sockent_client_connect */
/* Open the file descriptors for a initialized sockent structure. */
static int sockent_server_listen (sockent_t *se) /* {{{ */
tmp = (int) ci->values[0].value.number;
if ((tmp > 0) && (tmp <= 255))
network_config_ttl = tmp;
+ else {
+ WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
+ return (-1);
+ }
return (0);
} /* }}} int network_config_set_ttl */
if (strcasecmp ("Interface", child->key) == 0)
network_config_set_interface (child,
&se->interface);
+ else if (strcasecmp ("ResolveInterval", child->key) == 0)
+ cf_util_get_cdtime(child, &se->data.client.resolve_interval);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
{
int i;
+ /* The options need to be applied first */
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("TimeToLive", child->key) == 0)
+ network_config_set_ttl (child);
+ }
+
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
network_config_add_listen (child);
else if (strcasecmp ("Server", child->key) == 0)
network_config_add_server (child);
- else if (strcasecmp ("TimeToLive", child->key) == 0)
- network_config_set_ttl (child);
+ else if (strcasecmp ("TimeToLive", child->key) == 0) {
+ /* Handled earlier */
+ }
else if (strcasecmp ("MaxPacketSize", child->key) == 0)
network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)