Merge branch 'collectd-4.4' into collectd-4.5
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sat, 24 Jan 2009 10:04:22 +0000 (11:04 +0100)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sat, 24 Jan 2009 10:04:22 +0000 (11:04 +0100)
1  2 
contrib/cussh.pl
src/ascent.c
src/tcpconns.c
src/utils_cache.c

diff --combined contrib/cussh.pl
@@@ -62,6 -62,7 +62,7 @@@ use Collectd::Unixsock()
                GETVAL  => \&getval,
                FLUSH   => \&flush,
                LISTVAL => \&listval,
+               PUTNOTIF => \&putnotif,
        };
  
        if (! $sock) {
@@@ -163,6 -164,7 +164,7 @@@ Available commands
    GETVAL
    FLUSH
    LISTVAL
+   PUTNOTIF
  
  See the embedded Perldoc documentation for details. To do that, run:
    perldoc $0
@@@ -243,15 -245,6 +245,15 @@@ sub flush 
                        elsif ($option eq "timeout") {
                                $args{"timeout"} = $value;
                        }
 +                      elsif ($option eq "identifier") {
 +                              my $id = getid (\$value);
 +                              if (!$id)
 +                              {
 +                                      print STDERR "Not a valid identifier: \"$value\"\n";
 +                                      next;
 +                              }
 +                              push @{$args{"identifier"}}, $id;
 +                      }
                        else {
                                print STDERR "Invalid option \"$option\".\n";
                                return;
@@@ -290,6 -283,29 +292,29 @@@ sub listval 
        return 1;
  }
  
+ =item B<PUTNOTIF> [[B<severity>=I<$severity>] [B<message>=I<$message>] [ ...]]
+ =cut
+ sub putnotif {
+       my $sock = shift || return;
+       my $line = shift || return;
+       my (%values) = ();
+       foreach my $i (split m/ /, $line) {
+               my($key,$val) = split m/=/, $i, 2;
+               if ($key && $val) {
+                       $values{$key} = $val;
+               }
+               else {
+                       $values{'message'} .= ' '.$key;
+               }
+       }
+       $values{'time'} ||= time();
+       my(@tmp) = %values;
+       return $sock->putnotif(%values);
+ }
  =back
  
  These commands follow the exact same syntax as described in
diff --combined src/ascent.c
@@@ -91,12 -91,10 +91,12 @@@ struct player_info_
  typedef struct player_info_s player_info_t;
  #define PLAYER_INFO_STATIC_INIT { -1, -1, -1, -1, -1 }
  
 -static char *url    = NULL;
 -static char *user   = NULL;
 -static char *pass   = NULL;
 -static char *cacert = NULL;
 +static char *url         = NULL;
 +static char *user        = NULL;
 +static char *pass        = NULL;
 +static char *verify_peer = NULL;
 +static char *verify_host = NULL;
 +static char *cacert      = NULL;
  
  static CURL *curl = NULL;
  
@@@ -110,8 -108,6 +110,8 @@@ static const char *config_keys[] 
    "URL",
    "User",
    "Password",
 +  "VerifyPeer",
 +  "VerifyHost",
    "CACert"
  };
  static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
@@@ -134,12 -130,10 +134,12 @@@ static int ascent_submit_gauge (const c
      sstrncpy (vl.plugin_instance, plugin_instance,
          sizeof (vl.plugin_instance));
  
 +  sstrncpy (vl.type, type, sizeof (vl.type));
 +
    if (type_instance != NULL)
      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
    return (0);
  } /* }}} int ascent_submit_gauge */
  
@@@ -277,10 -271,12 +277,12 @@@ static int ascent_xml_submit_gauge (xml
      value = strtod (str_ptr, &end_ptr);
      if (str_ptr == end_ptr)
      {
+       xmlFree(str_ptr);
        ERROR ("ascent plugin: ascent_xml_submit_gauge: strtod failed.");
        return (-1);
      }
    }
+   xmlFree(str_ptr);
  
    return (ascent_submit_gauge (plugin_instance, type, type_instance, value));
  } /* }}} int ascent_xml_submit_gauge */
@@@ -306,10 -302,12 +308,12 @@@ static int ascent_xml_read_int (xmlDoc 
      value = strtol (str_ptr, &end_ptr, 0);
      if (str_ptr == end_ptr)
      {
+       xmlFree(str_ptr);
        ERROR ("ascent plugin: ascent_xml_read_int: strtol failed.");
        return (-1);
      }
    }
+   xmlFree(str_ptr);
  
    *ret_value = value;
    return (0);
@@@ -504,10 -502,6 +508,10 @@@ static int ascent_config (const char *k
      return (config_set (&user, value));
    else if (strcasecmp (key, "Password") == 0)
      return (config_set (&pass, value));
 +  else if (strcasecmp (key, "VerifyPeer") == 0)
 +    return (config_set (&verify_peer, value));
 +  else if (strcasecmp (key, "VerifyHost") == 0)
 +    return (config_set (&verify_host, value));
    else if (strcasecmp (key, "CACert") == 0)
      return (config_set (&cacert, value));
    else
@@@ -544,7 -538,7 +548,7 @@@ static int ascent_init (void) /* {{{ *
    {
      int status;
  
 -    status = snprintf (credentials, sizeof (credentials), "%s:%s",
 +    status = ssnprintf (credentials, sizeof (credentials), "%s:%s",
          user, (pass == NULL) ? "" : pass);
      if (status >= sizeof (credentials))
      {
            "credentials have been truncated.");
        return (-1);
      }
 -    credentials[sizeof (credentials) - 1] = '\0';
  
      curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
    }
  
    curl_easy_setopt (curl, CURLOPT_URL, url);
  
 +  if ((verify_peer == NULL) || (strcmp (verify_peer, "true") == 0))
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1);
 +  else
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0);
 +
 +  if ((verify_host == NULL) || (strcmp (verify_host, "true") == 0))
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2);
 +  else
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
 +
    if (cacert != NULL)
      curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
  
diff --combined src/tcpconns.c
   *   Florian octo Forster <octo at verplant.org>
   **/
  
 +/**
 + * Code within `HAVE_LIBKVM_NLIST' blocks is provided under the following
 + * license:
 + *
 + * $collectd: parts of tcpconns.c, 2008/08/08 03:48:30 Michael Stapelberg $
 + * $OpenBSD: inet.c,v 1.100 2007/06/19 05:28:30 ray Exp $
 + * $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $
 + *
 + * Copyright (c) 1983, 1988, 1993
 + *      The Regents of the University of California.  All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + * 3. Neither the name of the University nor the names of its contributors
 + *    may be used to endorse or promote products derived from this software
 + *    without specific prior written permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 + * SUCH DAMAGE.
 + */
 +
  #include "collectd.h"
  #include "common.h"
  #include "plugin.h"
  
 -#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME
 +#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_LIBKVM_NLIST
  # error "No applicable input method."
  #endif
  
  # include <netinet/tcpip.h>
  # include <netinet/tcp_seq.h>
  # include <netinet/tcp_var.h>
 -#endif /* HAVE_SYSCTLBYNAME */
 +/* #endif HAVE_SYSCTLBYNAME */
 +
 +/* This is for OpenBSD and possibly NetBSD. */
 +#elif HAVE_LIBKVM_NLIST
 +# include <sys/queue.h>
 +# include <sys/socket.h>
 +# include <net/route.h>
 +# include <netinet/in.h>
 +# include <netinet/in_systm.h>
 +# include <netinet/ip.h>
 +# include <netinet/in_pcb.h>
 +# include <netinet/tcp.h>
 +# include <netinet/tcp_timer.h>
 +# include <netinet/tcp_var.h>
 +# include <netdb.h>
 +# include <arpa/inet.h>
 +# include <nlist.h>
 +# include <kvm.h>
 +#endif /* HAVE_LIBKVM_NLIST */
  
  #if KERNEL_LINUX
  static const char *tcp_state[] =
@@@ -154,32 -100,7 +154,32 @@@ static const char *tcp_state[] 
  # define TCP_STATE_LISTEN 1
  # define TCP_STATE_MIN 0
  # define TCP_STATE_MAX 10
 -#endif /* HAVE_SYSCTLBYNAME */
 +/* #endif HAVE_SYSCTLBYNAME */
 +
 +#elif HAVE_LIBKVM_NLIST
 +static const char *tcp_state[] =
 +{
 +  "CLOSED",
 +  "LISTEN",
 +  "SYN_SENT",
 +  "SYN_RECV",
 +  "ESTABLISHED",
 +  "CLOSE_WAIT",
 +  "FIN_WAIT1",
 +  "CLOSING",
 +  "LAST_ACK",
 +  "FIN_WAIT2",
 +  "TIME_WAIT"
 +};
 +
 +static kvm_t *kvmd;
 +static u_long      inpcbtable_off = 0;
 +struct inpcbtable *inpcbtable_ptr = NULL;
 +
 +# define TCP_STATE_LISTEN 1
 +# define TCP_STATE_MIN 1
 +# define TCP_STATE_MAX 10
 +#endif /* HAVE_LIBKVM_NLIST */
  
  #define PORT_COLLECT_LOCAL  0x01
  #define PORT_COLLECT_REMOTE 0x02
@@@ -216,36 -137,39 +216,36 @@@ static void conn_submit_port_entry (por
    vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "tcpconns", sizeof (vl.plugin));
 +  sstrncpy (vl.type, "tcp_connections", sizeof (vl.type));
  
    if (((port_collect_listening != 0) && (pe->flags & PORT_IS_LISTENING))
        || (pe->flags & PORT_COLLECT_LOCAL))
    {
 -    snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
 +    ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
        "%"PRIu16"-local", pe->port);
 -    vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
  
      for (i = 1; i <= TCP_STATE_MAX; i++)
      {
        vl.values[0].gauge = pe->count_local[i];
  
 -      strncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
 -      vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +      sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("tcp_connections", &vl);
 +      plugin_dispatch_values (&vl);
      }
    }
  
    if (pe->flags & PORT_COLLECT_REMOTE)
    {
 -    snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
 +    ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
        "%"PRIu16"-remote", pe->port);
 -    vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
  
      for (i = 1; i <= TCP_STATE_MAX; i++)
      {
        vl.values[0].gauge = pe->count_remote[i];
  
 -      strncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
 -      vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +      sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("tcp_connections", &vl);
 +      plugin_dispatch_values (&vl);
      }
    }
  } /* void conn_submit */
@@@ -439,10 -363,7 +439,10 @@@ static int conn_read_file (const char *
  /* #endif KERNEL_LINUX */
  
  #elif HAVE_SYSCTLBYNAME
 -#endif /* HAVE_SYSCTLBYNAME */
 +/* #endif HAVE_SYSCTLBYNAME */
 +
 +#elif HAVE_LIBKVM_NLIST
 +#endif /* HAVE_LIBKVM_NLIST */
  
  static int conn_config (const char *key, const char *value)
  {
@@@ -585,7 -506,8 +585,8 @@@ static int conn_read (void
        && ((inp->inp_vflag & INP_IPV6) == 0))
        continue;
  
-     conn_handle_ports (inp->inp_lport, inp->inp_fport, tp->t_state);
+     conn_handle_ports (ntohs (inp->inp_lport), ntohs (inp->inp_fport),
+       tp->t_state);
    } /* for (in_ptr) */
  
    in_orig = NULL;
  
    return (0);
  } /* int conn_read */
 -#endif /* HAVE_SYSCTLBYNAME */
 +/* #endif HAVE_SYSCTLBYNAME */
 +
 +#elif HAVE_LIBKVM_NLIST
 +static int kread (u_long addr, void *buf, int size)
 +{
 +  int status;
 +
 +  status = kvm_read (kvmd, addr, buf, size);
 +  if (status != size)
 +  {
 +    ERROR ("tcpconns plugin: kvm_read failed (got %i, expected %i): %s\n",
 +      status, size, kvm_geterr (kvmd));
 +    return (-1);
 +  }
 +  return (0);
 +} /* int kread */
 +
 +static int conn_init (void)
 +{
 +  char buf[_POSIX2_LINE_MAX];
 +  struct nlist nl[] =
 +  {
 +#define N_TCBTABLE 0
 +    { "_tcbtable" },
 +    { "" }
 +  };
 +  int status;
 +
 +  kvmd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, buf);
 +  if (kvmd == NULL)
 +  {
 +    ERROR ("tcpconns plugin: kvm_openfiles failed: %s", buf);
 +    return (-1);
 +  }
 +
 +  status = kvm_nlist (kvmd, nl);
 +  if (status < 0)
 +  {
 +    ERROR ("tcpconns plugin: kvm_nlist failed with status %i.", status);
 +    return (-1);
 +  }
 +
 +  if (nl[N_TCBTABLE].n_type == 0)
 +  {
 +    ERROR ("tcpconns plugin: Error looking up kernel's namelist: "
 +      "N_TCBTABLE is invalid.");
 +    return (-1);
 +  }
 +
 +  inpcbtable_off = (u_long) nl[N_TCBTABLE].n_value;
 +  inpcbtable_ptr = (struct inpcbtable *) nl[N_TCBTABLE].n_value;
 +
 +  return (0);
 +} /* int conn_init */
 +
 +static int conn_read (void)
 +{
 +  struct inpcbtable table;
 +  struct inpcb *head;
 +  struct inpcb *next;
 +  struct inpcb inpcb;
 +  struct tcpcb tcpcb;
 +  int status;
 +
 +  conn_reset_port_entry ();
 +
 +  /* Read the pcbtable from the kernel */
 +  status = kread (inpcbtable_off, &table, sizeof (table));
 +  if (status != 0)
 +    return (-1);
 +
 +  /* Get the `head' pcb */
 +  head = (struct inpcb *) &(inpcbtable_ptr->inpt_queue);
 +  /* Get the first pcb */
 +  next = CIRCLEQ_FIRST (&table.inpt_queue);
 +
 +  while (next != head)
 +  {
 +    /* Read the pcb pointed to by `next' into `inpcb' */
 +    kread ((u_long) next, &inpcb, sizeof (inpcb));
 +
 +    /* Advance `next' */
 +    next = CIRCLEQ_NEXT (&inpcb, inp_queue);
 +
 +    /* Ignore sockets, that are not connected. */
 +    if (!(inpcb.inp_flags & INP_IPV6)
 +      && (inet_lnaof(inpcb.inp_laddr) == INADDR_ANY))
 +      continue;
 +    if ((inpcb.inp_flags & INP_IPV6)
 +      && IN6_IS_ADDR_UNSPECIFIED (&inpcb.inp_laddr6))
 +      continue;
 +
 +    kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
 +    conn_handle_ports (ntohs(inpcb.inp_lport), ntohs(inpcb.inp_fport), tcpcb.t_state);
 +  } /* while (next != head) */
 +
 +  conn_submit_all ();
 +
 +  return (0);
 +}
 +#endif /* HAVE_LIBKVM_NLIST */
  
  void module_register (void)
  {
                        config_keys, config_keys_num);
  #if KERNEL_LINUX
        plugin_register_init ("tcpconns", conn_init);
 +#elif HAVE_SYSCTLBYNAME
 +      /* no initialization */
 +#elif HAVE_LIBKVM_NLIST
 +      plugin_register_init ("tcpconns", conn_init);
  #endif
        plugin_register_read ("tcpconns", conn_read);
  } /* void module_register */
  
  /*
 - * vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
 + * vim: set shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker :
   */
diff --combined src/utils_cache.c
@@@ -156,12 -156,13 +156,12 @@@ static int uc_send_notification (const 
      return (-1);
    }
  
 -  snprintf (n.message, sizeof (n.message),
 +  ssnprintf (n.message, sizeof (n.message),
        "%s has not been updated for %i seconds.", name,
        (int) (n.time - ce->last_update));
  
    pthread_mutex_unlock (&cache_lock);
  
 -  n.message[sizeof (n.message) - 1] = '\0';
    plugin_dispatch_notification (&n);
  
    return (0);
@@@ -186,6 -187,7 +186,7 @@@ static int uc_insert (const data_set_t 
    ce = cache_alloc (ds->ds_num);
    if (ce == NULL)
    {
+     sfree (key_copy);
      ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
      return (-1);
    }
@@@ -261,6 -263,7 +262,7 @@@ int uc_check_timeout (void
        {
        ERROR ("uc_purge: realloc failed.");
        c_avl_iterator_destroy (iter);
+       pthread_mutex_unlock (&cache_lock);
        return (-1);
        }
  
      }
      else
      {
 -      WARNING ("uc_check_timeout: ut_check_interesting (%s) returned ",
 +      WARNING ("uc_check_timeout: ut_check_interesting (%s) returned "
          "invalid status %i.",
          keys[i], status);
      }
@@@ -450,9 -453,10 +452,9 @@@ int uc_update (const data_set_t *ds, co
    n.severity = NOTIF_OKAY;
    n.time = vl->time;
  
 -  snprintf (n.message, sizeof (n.message),
 +  ssnprintf (n.message, sizeof (n.message),
        "Received a value for %s. It was missing for %u seconds.",
        name, (unsigned int) update_delay);
 -  n.message[sizeof (n.message) - 1] = '\0';
  
    plugin_dispatch_notification (&n);
  
@@@ -523,7 -527,7 +525,7 @@@ gauge_t *uc_get_rate (const data_set_t 
    if (ret_num != ds->ds_num)
    {
      ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
 -      "but uc_get_rate_by_name returned %i.",
 +      "but uc_get_rate_by_name returned %zu.",
        ds->type, ds->ds_num, ret_num);
      sfree (ret);
      return (NULL);