Merge branch 'collectd-4.5' into collectd-4.6
[collectd.git] / src / powerdns.c
index 06d8d2e..164137b 100644 (file)
 #endif
 #define FUNC_ERROR(func) do { char errbuf[1024]; ERROR ("powerdns plugin: %s failed: %s", func, sstrerror (errno, errbuf, sizeof (errbuf))); } while (0)
 
-#define SERVER_SOCKET  "/var/run/pdns.controlsocket"
+#define SERVER_SOCKET  LOCALSTATEDIR"/run/pdns.controlsocket"
 #define SERVER_COMMAND "SHOW *"
 
-#define RECURSOR_SOCKET  "/var/run/pdns_recursor.controlsocket"
-#define RECURSOR_COMMAND "get all-outqueries answers0-1 " /* {{{ */ \
-  "answers100-1000 answers10-100 answers1-10 answers-slow cache-entries " \
-  "cache-hits cache-misses chain-resends client-parse-errors " \
-  "concurrent-queries dlg-only-drops ipv6-outqueries negcache-entries " \
-  "noerror-answers nsset-invalidations nsspeeds-entries nxdomain-answers " \
-  "outgoing-timeouts qa-latency questions resource-limits " \
-  "server-parse-errors servfail-answers spoof-prevents sys-msec " \
-  "tcp-client-overflow tcp-outqueries tcp-questions throttled-out " \
-  "throttled-outqueries throttle-entries unauthorized-tcp unauthorized-udp " \
-  "unexpected-packets unreachables user-msec" /* }}} */
+#define RECURSOR_SOCKET  LOCALSTATEDIR"/run/pdns_recursor.controlsocket"
+#define RECURSOR_COMMAND "get noerror-answers nxdomain-answers " \
+  "servfail-answers sys-msec user-msec qa-latency cache-entries cache-hits " \
+  "cache-misses questions"
 
 struct list_item_s;
 typedef struct list_item_s list_item_t;
@@ -67,7 +60,7 @@ struct list_item_s
 {
   enum
   {
-    SRV_AUTHORATIVE,
+    SRV_AUTHORITATIVE,
     SRV_RECURSOR
   } server_type;
   int (*func) (list_item_t *item);
@@ -128,6 +121,23 @@ uptime              number of seconds process has been running (since 3.1.5)
 user-msec           number of CPU milliseconds spent in 'user' mode
 }}} */
 
+const char* const default_server_fields[] = /* {{{ */
+{
+  "latency"
+  "packetcache-hit",
+  "packetcache-miss",
+  "packetcache-size",
+  "query-cache-hit",
+  "query-cache-miss",
+  "recursing-answers",
+  "recursing-questions",
+  "tcp-answers",
+  "tcp-queries",
+  "udp-answers",
+  "udp-queries",
+}; /* }}} */
+int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
+
 statname_lookup_t lookup_table[] = /* {{{ */
 {
   /*********************
@@ -254,7 +264,7 @@ static void submit (const char *plugin_instance, /* {{{ */
 
   if (i >= lookup_table_length)
   {
-    DEBUG ("powerdns plugin: submit: Not found in lookup table: %s = %s;",
+    INFO ("powerdns plugin: submit: Not found in lookup table: %s = %s;",
         pdns_type, value);
     return;
   }
@@ -307,14 +317,14 @@ static void submit (const char *plugin_instance, /* {{{ */
 
   vl.values = values;
   vl.values_len = 1;
-  vl.time = time (NULL);
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin));
+  sstrncpy (vl.type, type, sizeof (vl.type));
   if (type_instance != NULL)
     sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
   sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 
-  plugin_dispatch_values (type, &vl);
+  plugin_dispatch_values (&vl);
 } /* }}} static void submit */
 
 static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
@@ -339,10 +349,9 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
 
   memset (&sa_unix, 0, sizeof (sa_unix));
   sa_unix.sun_family = AF_UNIX;
-  strncpy (sa_unix.sun_path,
+  sstrncpy (sa_unix.sun_path,
       (local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
       sizeof (sa_unix.sun_path));
-  sa_unix.sun_path[sizeof (sa_unix.sun_path) - 1] = 0;
 
   status = unlink (sa_unix.sun_path);
   if ((status != 0) && (errno != ENOENT))
@@ -392,6 +401,7 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
       FUNC_ERROR ("recv");
       break;
     }
+    buffer_size = status + 1;
     status = 0;
   } while (0);
 
@@ -401,7 +411,7 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
   if (status != 0)
     return (-1);
 
-  buffer_size = status + 1;
+  assert (buffer_size > 0);
   buffer = (char *) malloc (buffer_size);
   if (buffer == NULL)
   {
@@ -409,8 +419,8 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
     return (-1);
   }
 
-  memcpy (buffer, temp, status);
-  buffer[status] = 0;
+  memcpy (buffer, temp, buffer_size - 1);
+  buffer[buffer_size - 1] = 0;
 
   *ret_buffer = buffer;
   *ret_buffer_size = buffer_size;
@@ -524,6 +534,9 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */
   char *key;
   char *value;
 
+  const char* const *fields;
+  int fields_num;
+
   if (item->command == NULL)
     item->command = strdup ("SHOW *");
   if (item->command == NULL)
@@ -536,6 +549,20 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */
   if (status != 0)
     return (-1);
 
+  if (item->fields_num != 0)
+  {
+    fields = (const char* const *) item->fields;
+    fields_num = item->fields_num;
+  }
+  else
+  {
+    fields = default_server_fields;
+    fields_num = default_server_fields_num;
+  }
+
+  assert (fields != NULL);
+  assert (fields_num > 0);
+
   /* corrupt-packets=0,deferred-cache-inserts=0,deferred-cache-lookup=0,latency=0,packetcache-hit=0,packetcache-miss=0,packetcache-size=0,qsize-q=0,query-cache-hit=0,query-cache-miss=0,recursing-answers=0,recursing-questions=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,udp4-answers=0,udp4-queries=0,udp6-answers=0,udp6-queries=0, */
   dummy = buffer;
   saveptr = NULL;
@@ -556,10 +583,10 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */
       continue;
 
     /* Check if this item was requested. */
-    for (i = 0; i < item->fields_num; i++)
-      if (strcasecmp (key, item->fields[i]) == 0)
+    for (i = 0; i < fields_num; i++)
+      if (strcasecmp (key, fields[i]) == 0)
        break;
-    if (i >= item->fields_num)
+    if (i >= fields_num)
       continue;
 
     submit (item->instance, key, value);
@@ -582,19 +609,27 @@ static int powerdns_update_recursor_command (list_item_t *li) /* {{{ */
   char buffer[4096];
   int status;
 
-  if (li != NULL)
+  if (li == NULL)
     return (0);
 
-  strcpy (buffer, "get ");
-  status = strjoin (&buffer[4], sizeof (buffer) - strlen ("get "),
-      li->fields, li->fields_num,
-      /* seperator = */ " ");
-  if (status < 0)
+  if (li->fields_num < 1)
   {
-    ERROR ("powerdns plugin: strjoin failed.");
-    return (-1);
+    sstrncpy (buffer, RECURSOR_COMMAND, sizeof (buffer));
+  }
+  else
+  {
+    sstrncpy (buffer, "get ", sizeof (buffer));
+    status = strjoin (&buffer[4], sizeof (buffer) - strlen ("get "),
+       li->fields, li->fields_num,
+       /* seperator = */ " ");
+    if (status < 0)
+    {
+      ERROR ("powerdns plugin: strjoin failed.");
+      return (-1);
+    }
   }
 
+  buffer[sizeof (buffer) - 1] = 0;
   li->command = strdup (buffer);
   if (li->command == NULL)
   {
@@ -627,12 +662,18 @@ static int powerdns_read_recursor (list_item_t *item) /* {{{ */
       ERROR ("powerdns plugin: powerdns_update_recursor_command failed.");
       return (-1);
     }
+
+    DEBUG ("powerdns plugin: powerdns_read_recursor: item->command = %s;",
+        item->command);
   }
   assert (item->command != NULL);
 
   status = powerdns_get_data (item, &buffer, &buffer_size);
   if (status != 0)
+  {
+    ERROR ("powerdns plugin: powerdns_get_data failed.");
     return (-1);
+  }
 
   keys_list = strdup (item->command);
   if (keys_list == NULL)
@@ -768,7 +809,7 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
    */
   if (strcasecmp ("Server", ci->key) == 0)
   {
-    item->server_type = SRV_AUTHORATIVE;
+    item->server_type = SRV_AUTHORITATIVE;
     item->func = powerdns_read_server;
     item->socktype = SOCK_STREAM;
     socket_temp = strdup (SERVER_SOCKET);
@@ -817,15 +858,9 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
       break;
     }
 
-    if (item->command == NULL)
-    {
-      ERROR ("powerdns plugin: item->command == NULL.");
-      status = -1;
-      break;
-    }
-
     item->sockaddr.sun_family = AF_UNIX;
-    sstrncpy (item->sockaddr.sun_path, socket_temp, UNIX_PATH_MAX);
+    sstrncpy (item->sockaddr.sun_path, socket_temp,
+      sizeof (item->sockaddr.sun_path));
 
     e = llentry_create (item->instance, item);
     if (e == NULL)
@@ -874,7 +909,7 @@ static int powerdns_config (oconfig_item_t *ci) /* {{{ */
     if ((strcasecmp ("Server", option->key) == 0)
        || (strcasecmp ("Recursor", option->key) == 0))
       powerdns_config_add_server (option);
-    if (strcasecmp ("LocalSocket", option->key) == 0)
+    else if (strcasecmp ("LocalSocket", option->key) == 0)
     {
       char *temp = strdup (option->key);
       if (temp == NULL)