Code

Merge remote-tracking branch 'github/pr/387'
[collectd.git] / src / dns.c
index 364b9587e19c5c49ac6010049c2befa8f503ea35..00fcff191e0ccf0177ec7bea309eb2964b331228 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -33,9 +33,7 @@
 #include <poll.h>
 
 #include <pcap.h>
-#if HAVE_PCAP_BPF_H
-# include <pcap-bpf.h>
-#endif
+#include <pcap-bpf.h>
 
 /*
  * Private data types
@@ -63,8 +61,8 @@ static int select_numeric_qtype = 1;
 #define PCAP_SNAPLEN 1460
 static char   *pcap_device = NULL;
 
-static counter_t       tr_queries;
-static counter_t       tr_responses;
+static derive_t       tr_queries;
+static derive_t       tr_responses;
 static counter_list_t *qtype_list;
 static counter_list_t *opcode_list;
 static counter_list_t *rcode_list;
@@ -84,14 +82,10 @@ static counter_list_t *counter_list_search (counter_list_t **list, unsigned int
 {
        counter_list_t *entry;
 
-       DEBUG ("counter_list_search (list = %p, key = %u)",
-                       (void *) *list, key);
-
        for (entry = *list; entry != NULL; entry = entry->next)
                if (entry->key == key)
                        break;
 
-       DEBUG ("return (%p)", (void *) entry);
        return (entry);
 }
 
@@ -100,9 +94,6 @@ static counter_list_t *counter_list_create (counter_list_t **list,
 {
        counter_list_t *entry;
 
-       DEBUG ("counter_list_create (list = %p, key = %u, value = %u)",
-                       (void *) *list, key, value);
-
        entry = (counter_list_t *) malloc (sizeof (counter_list_t));
        if (entry == NULL)
                return (NULL);
@@ -126,7 +117,6 @@ static counter_list_t *counter_list_create (counter_list_t **list,
                last->next = entry;
        }
 
-       DEBUG ("return (%p)", (void *) entry);
        return (entry);
 }
 
@@ -135,9 +125,6 @@ static void counter_list_add (counter_list_t **list,
 {
        counter_list_t *entry;
 
-       DEBUG ("counter_list_add (list = %p, key = %u, increment = %u)",
-                       (void *) *list, key, increment);
-
        entry = counter_list_search (list, key);
 
        if (entry != NULL)
@@ -148,7 +135,6 @@ static void counter_list_add (counter_list_t **list,
        {
                counter_list_create (list, key, increment);
        }
-       DEBUG ("return ()");
 }
 
 static int dns_config (const char *key, const char *value)
@@ -222,7 +208,7 @@ static void dns_child_callback (const rfc1035_header_t *dns)
        pthread_mutex_unlock (&opcode_mutex);
 }
 
-static void *dns_child_loop (__attribute__((unused)) void *dummy)
+static int dns_run_pcap_loop (void)
 {
        pcap_t *pcap_obj;
        char    pcap_error[PCAP_ERRBUF_SIZE];
@@ -242,7 +228,7 @@ static void *dns_child_loop (__attribute__((unused)) void *dummy)
        pcap_obj = pcap_open_live ((pcap_device != NULL) ? pcap_device : "any",
                        PCAP_SNAPLEN,
                        0 /* Not promiscuous */,
-                       interval_g,
+                       (int) CDTIME_T_TO_MS (plugin_get_interval () / 2),
                        pcap_error);
        if (pcap_obj == NULL)
        {
@@ -250,22 +236,27 @@ static void *dns_child_loop (__attribute__((unused)) void *dummy)
                                "failed: %s",
                                (pcap_device != NULL) ? pcap_device : "any",
                                pcap_error);
-               return (NULL);
+               return (PCAP_ERROR);
        }
 
        memset (&fp, 0, sizeof (fp));
-       if (pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0) < 0)
+       status = pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0);
+       if (status < 0)
        {
-               ERROR ("dns plugin: pcap_compile failed");
-               return (NULL);
+               ERROR ("dns plugin: pcap_compile failed: %s",
+                               pcap_statustostr (status));
+               return (status);
        }
-       if (pcap_setfilter (pcap_obj, &fp) < 0)
+
+       status = pcap_setfilter (pcap_obj, &fp);
+       if (status < 0)
        {
-               ERROR ("dns plugin: pcap_setfilter failed");
-               return (NULL);
+               ERROR ("dns plugin: pcap_setfilter failed: %s",
+                               pcap_statustostr (status));
+               return (status);
        }
 
-       DEBUG ("PCAP object created.");
+       DEBUG ("dns plugin: PCAP object created.");
 
        dnstop_set_pcap_obj (pcap_obj);
        dnstop_set_callback (dns_child_callback);
@@ -273,19 +264,65 @@ static void *dns_child_loop (__attribute__((unused)) void *dummy)
        status = pcap_loop (pcap_obj,
                        -1 /* loop forever */,
                        handle_pcap /* callback */,
-                       NULL /* Whatever this means.. */);
-       if (status < 0)
-               ERROR ("dns plugin: Listener thread is exiting "
-                               "abnormally: %s", pcap_geterr (pcap_obj));
-
-       DEBUG ("child is exiting");
+                       NULL /* user data */);
+       INFO ("dns plugin: pcap_loop exited with status %i.", status);
+       /* We need to handle "PCAP_ERROR" specially because libpcap currently
+        * doesn't return PCAP_ERROR_IFACE_NOT_UP for compatibility reasons. */
+       if (status == PCAP_ERROR)
+               status = PCAP_ERROR_IFACE_NOT_UP;
 
        pcap_close (pcap_obj);
-       listen_thread_init = 0;
-       pthread_exit (NULL);
+       return (status);
+} /* int dns_run_pcap_loop */
+
+static int dns_sleep_one_interval (void) /* {{{ */
+{
+       cdtime_t interval;
+       struct timespec ts = { 0, 0 };
+       int status = 0;
 
+       interval = plugin_get_interval ();
+       CDTIME_T_TO_TIMESPEC (interval, &ts);
+
+       while (42)
+       {
+               struct timespec rem = { 0, 0 };
+
+               status = nanosleep (&ts, &rem);
+               if (status == 0)
+                       break;
+               else if ((errno == EINTR) || (errno == EAGAIN))
+               {
+                       ts = rem;
+                       continue;
+               }
+               else
+                       break;
+       }
+
+       return (status);
+} /* }}} int dns_sleep_one_interval */
+
+static void *dns_child_loop (__attribute__((unused)) void *dummy) /* {{{ */
+{
+       int status;
+
+       while (42)
+       {
+               status = dns_run_pcap_loop ();
+               if (status != PCAP_ERROR_IFACE_NOT_UP)
+                       break;
+
+               dns_sleep_one_interval ();
+       }
+
+       if (status != PCAP_ERROR_BREAK)
+               ERROR ("dns plugin: PCAP returned error %s.",
+                               pcap_statustostr (status));
+
+       listen_thread_init = 0;
        return (NULL);
-} /* static void dns_child_loop (void) */
+} /* }}} void *dns_child_loop */
 
 static int dns_init (void)
 {
@@ -300,7 +337,7 @@ static int dns_init (void)
        if (listen_thread_init != 0)
                return (-1);
 
-       status = pthread_create (&listen_thread, NULL, dns_child_loop,
+       status = plugin_thread_create (&listen_thread, NULL, dns_child_loop,
                        (void *) 0);
        if (status != 0)
        {
@@ -315,13 +352,13 @@ static int dns_init (void)
        return (0);
 } /* int dns_init */
 
-static void submit_counter (const char *type, const char *type_instance,
-               counter_t value)
+static void submit_derive (const char *type, const char *type_instance,
+               derive_t value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].counter = value;
+       values[0].derive = value;
 
        vl.values = values;
        vl.values_len = 1;
@@ -331,15 +368,15 @@ static void submit_counter (const char *type, const char *type_instance,
        sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
        plugin_dispatch_values (&vl);
-} /* void submit_counter */
+} /* void submit_derive */
 
-static void submit_octets (counter_t queries, counter_t responses)
+static void submit_octets (derive_t queries, derive_t responses)
 {
        value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].counter = queries;
-       values[1].counter = responses;
+       values[0].derive = queries;
+       values[1].derive = responses;
 
        vl.values = values;
        vl.values_len = 2;
@@ -348,7 +385,7 @@ static void submit_octets (counter_t queries, counter_t responses)
        sstrncpy (vl.type, "dns_octets", sizeof (vl.type));
 
        plugin_dispatch_values (&vl);
-} /* void submit_counter */
+} /* void submit_octets */
 
 static int dns_read (void)
 {
@@ -379,8 +416,8 @@ static int dns_read (void)
 
        for (i = 0; i < len; i++)
        {
-               DEBUG ("qtype = %u; counter = %u;", keys[i], values[i]);
-               submit_counter ("dns_qtype", qtype_str (keys[i]), values[i]);
+               DEBUG ("dns plugin: qtype = %u; counter = %u;", keys[i], values[i]);
+               submit_derive ("dns_qtype", qtype_str (keys[i]), values[i]);
        }
 
        pthread_mutex_lock (&opcode_mutex);
@@ -395,8 +432,8 @@ static int dns_read (void)
 
        for (i = 0; i < len; i++)
        {
-               DEBUG ("opcode = %u; counter = %u;", keys[i], values[i]);
-               submit_counter ("dns_opcode", opcode_str (keys[i]), values[i]);
+               DEBUG ("dns plugin: opcode = %u; counter = %u;", keys[i], values[i]);
+               submit_derive ("dns_opcode", opcode_str (keys[i]), values[i]);
        }
 
        pthread_mutex_lock (&rcode_mutex);
@@ -411,8 +448,8 @@ static int dns_read (void)
 
        for (i = 0; i < len; i++)
        {
-               DEBUG ("rcode = %u; counter = %u;", keys[i], values[i]);
-               submit_counter ("dns_rcode", rcode_str (keys[i]), values[i]);
+               DEBUG ("dns plugin: rcode = %u; counter = %u;", keys[i], values[i]);
+               submit_derive ("dns_rcode", rcode_str (keys[i]), values[i]);
        }
 
        return (0);