Merge branch 'collectd-5.4' into collectd-5.5
authorFlorian Forster <octo@collectd.org>
Wed, 17 Jun 2015 12:52:22 +0000 (14:52 +0200)
committerFlorian Forster <octo@collectd.org>
Wed, 17 Jun 2015 12:52:22 +0000 (14:52 +0200)
1  2 
src/email.c
src/liboconfig/parser.y
src/network.c

diff --combined src/email.c
@@@ -2,25 -2,20 +2,25 @@@
   * collectd - src/email.c
   * Copyright (C) 2006-2008  Sebastian Harl
   *
 - * This program is free software; you can redistribute it and/or modify it
 - * under the terms of the GNU General Public License as published by the
 - * Free Software Foundation; only version 2 of the License is applicable.
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the "Software"),
 + * to deal in the Software without restriction, including without limitation
 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 + * and/or sell copies of the Software, and to permit persons to whom the
 + * Software is furnished to do so, subject to the following conditions:
   *
 - * This program is distributed in the hope that it will be useful, but
 - * WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * General Public License for more details.
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
   *
 - * You should have received a copy of the GNU General Public License along
 - * with this program; if not, write to the Free Software Foundation, Inc.,
 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 + * DEALINGS IN THE SOFTWARE.
   *
 - * Author:
 + * Authors:
   *   Sebastian Harl <sh at tokkee.org>
   **/
  
@@@ -575,10 -570,27 +575,27 @@@ static int email_init (void
        return (0);
  } /* int email_init */
  
- static int email_shutdown (void)
+ static void type_list_free (type_list_t *t)
  {
-       type_t *ptr = NULL;
+       type_t *this;
+       this = t->head;
+       while (this != NULL)
+       {
+               type_t *next = this->next;
+               sfree (this->name);
+               sfree (this);
+               this = next;
+       }
+       t->head = NULL;
+       t->tail = NULL;
+ }
  
+ static int email_shutdown (void)
+ {
        int i = 0;
  
        if (connector != ((pthread_t) 0)) {
  
        pthread_mutex_unlock (&conns_mutex);
  
-       for (ptr = list_count.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-       for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-       for (ptr = list_size.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-       for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-       for (ptr = list_check.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-       for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
+       type_list_free (&list_count);
+       type_list_free (&list_count_copy);
+       type_list_free (&list_size);
+       type_list_free (&list_size_copy);
+       type_list_free (&list_check);
+       type_list_free (&list_check_copy);
  
        unlink ((NULL == sock_file) ? SOCK_PATH : sock_file);
  
diff --combined src/liboconfig/parser.y
@@@ -1,27 -1,19 +1,27 @@@
  /**
 - * oconfig - src/parser.y
 - * Copyright (C) 2007,2008  Florian octo Forster <octo at verplant.org>
 + * collectd - src/liboconfig/parser.y
 + * Copyright (C) 2007,2008  Florian Forster
   *
 - * This program is free software; you can redistribute it and/or modify it
 - * under the terms of the GNU General Public License as published by the
 - * Free Software Foundation; only version 2 of the License is applicable.
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the "Software"),
 + * to deal in the Software without restriction, including without limitation
 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 + * and/or sell copies of the Software, and to permit persons to whom the
 + * Software is furnished to do so, subject to the following conditions:
   *
 - * This program is distributed in the hope that it will be useful, but WITHOUT
 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 - * more details.
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
   *
 - * You should have received a copy of the GNU General Public License along with
 - * this program; if not, write to the Free Software Foundation, Inc.,
 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 + * DEALINGS IN THE SOFTWARE.
 + *
 + * Authors:
 + *   Florian Forster <octo at collectd.org>
   */
  
  %{
@@@ -36,6 -28,7 +36,7 @@@ static int yyerror (const char *s)
  /* Lexer variables */
  extern int yylineno;
  extern char *yytext;
+ extern int yylex (void);
  
  extern oconfig_item_t *ci_root;
  extern char           *c_file;
diff --combined src/network.c
@@@ -22,7 -22,6 +22,7 @@@
   *   Aman Gupta <aman at tmm1.net>
   **/
  
 +#define _DEFAULT_SOURCE
  #define _BSD_SOURCE /* For struct ip_mreq */
  
  #include "collectd.h"
@@@ -120,8 -119,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 -921,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 "
@@@ -2039,8 -2029,6 +2039,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 -2095,6 +2107,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) /* {{{ */
@@@ -2443,13 -2415,13 +2443,13 @@@ static int network_receive (void) /* {{
        int  buffer_len;
  
        int i;
-       int status;
+       int status = 0;
  
        receive_list_entry_t *private_list_head;
        receive_list_entry_t *private_list_tail;
        uint64_t              private_list_length;
  
-         assert (listen_sockets_num > 0);
+       assert (listen_sockets_num > 0);
  
        private_list_head = NULL;
        private_list_tail = NULL;
        while (listen_loop == 0)
        {
                status = poll (listen_sockets_pollfd, listen_sockets_num, -1);
                if (status <= 0)
                {
                        char errbuf[1024];
                        if (errno == EINTR)
                                continue;
-                       ERROR ("poll failed: %s",
+                       ERROR ("network plugin: poll(2) failed: %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
-                       return (-1);
+                       break;
                }
  
                for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
                        if (buffer_len < 0)
                        {
                                char errbuf[1024];
-                               ERROR ("recv failed: %s",
-                                               sstrerror (errno, errbuf,
-                                                       sizeof (errbuf)));
-                               return (-1);
+                               status = (errno != 0) ? errno : -1;
+                               ERROR ("network plugin: recv(2) failed: %s",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                               break;
                        }
  
                        stats_octets_rx += ((uint64_t) buffer_len);
                        if (ent == NULL)
                        {
                                ERROR ("network plugin: malloc failed.");
-                               return (-1);
+                               status = ENOMEM;
+                               break;
                        }
                        memset (ent, 0, sizeof (receive_list_entry_t));
                        ent->data = malloc (network_config_packet_size);
                        {
                                sfree (ent);
                                ERROR ("network plugin: malloc failed.");
-                               return (-1);
+                               status = ENOMEM;
+                               break;
                        }
                        ent->fd = listen_sockets_pollfd[i].fd;
                        ent->next = NULL;
                                private_list_tail = NULL;
                                private_list_length = 0;
                        }
+                       status = 0;
                } /* for (listen_sockets_pollfd) */
+               if (status != 0)
+                       break;
        } /* while (listen_loop == 0) */
  
        /* Make sure everything is dispatched before exiting. */
                pthread_mutex_unlock (&receive_list_lock);
        }
  
-       return (0);
+       return (status);
  } /* }}} int network_receive */
  
  static void *receive_thread (void __attribute__((unused)) *arg)
@@@ -3011,7 -2989,7 +3017,7 @@@ static int network_config_set_ttl (cons
      network_config_ttl = tmp;
    else {
      WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
 -    return (-1);    
 +    return (-1);
    }
  
    return (0);
@@@ -3238,8 -3216,6 +3244,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.",