Merge branch 'collectd-5.4' into collectd-5.5
authorFlorian Forster <octo@collectd.org>
Thu, 21 Jul 2016 05:49:25 +0000 (07:49 +0200)
committerFlorian Forster <octo@collectd.org>
Thu, 21 Jul 2016 05:49:25 +0000 (07:49 +0200)
1  2 
src/network.c

diff --combined src/network.c
@@@ -120,8 -120,6 +120,8 @@@ struct sockent_clien
        gcry_cipher_hd_t cypher;
        unsigned char password_hash[32];
  #endif
 +      cdtime_t next_resolve_reconnect;
 +      cdtime_t resolve_interval;
  };
  
  struct sockent_server
@@@ -924,19 -922,15 +924,19 @@@ static int parse_part_number (void **re
  } /* 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 "
@@@ -1444,6 -1435,7 +1444,7 @@@ static int parse_packet (sockent_t *se
                                printed_ignore_warning = 1;
                        }
                        buffer = ((char *) buffer) + pkg_length;
+                       buffer_size -= (size_t) pkg_length;
                        continue;
                }
  #endif /* HAVE_LIBGCRYPT */
                                printed_ignore_warning = 1;
                        }
                        buffer = ((char *) buffer) + pkg_length;
+                       buffer_size -= (size_t) pkg_length;
                        continue;
                }
  #endif /* HAVE_LIBGCRYPT */
                        DEBUG ("network plugin: parse_packet: Unknown part"
                                        " type: 0x%04hx", pkg_type);
                        buffer = ((char *) buffer) + pkg_length;
+                       buffer_size -= (size_t) pkg_length;
                }
        } /* while (buffer_size > sizeof (part_header_t)) */
  
@@@ -2039,8 -2033,6 +2042,8 @@@ static sockent_t *sockent_create (int t
        {
                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;
@@@ -2107,26 -2099,6 +2110,26 @@@ static int sockent_init_crypto (sockent
        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) /* {{{ */
@@@ -3240,8 -3216,6 +3243,8 @@@ static int network_config_add_server (c
      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.",