Code

dns plugin: Remove unnecessary poll code and use the (blocking) `pcap_loop' function...
[collectd.git] / src / dns.c
index da45a389ba1e8bae67d26886fbf9255d5f91d321..cd068fb363744b05c06f637a53ec248bd4d48ea5 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
 #include "plugin.h"
 #include "configfile.h"
 #include "utils_debug.h"
-
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
-#if HAVE_SYS_POLL_H
-# include <sys/poll.h>
-#endif
+#include "utils_dns.h"
 
 #define MODULE_NAME "dns"
 
-#if HAVE_LIBPCAP
-# define NAMED_HAVE_CONFIG 1
-#else
-# define NAMED_HAVE_CONFIG 0
-#endif
-
-#if HAVE_LIBPCAP && HAVE_PTHREAD_H
-# include "utils_dns.h"
-# define NAMED_HAVE_READ 1
+#if HAVE_LIBPCAP && HAVE_LIBPTHREAD
+# include <pthread.h>
+# include <pcap.h>
+# include <sys/poll.h>
+# define DNS_HAVE_READ 1
 #else
-# define NAMED_HAVE_READ 0
+# define DNS_HAVE_READ 0
 #endif
 
+/*
+ * Private data types
+ */
+#if DNS_HAVE_READ
 struct counter_list_s
 {
        unsigned int key;
@@ -56,7 +49,11 @@ struct counter_list_s
        struct counter_list_s *next;
 };
 typedef struct counter_list_s counter_list_t;
+#endif
 
+/*
+ * Private variables
+ */
 static char *traffic_file   = "dns/dns_traffic.rrd";
 static char *qtype_file   = "dns/qtype-%s.rrd";
 static char *opcode_file  = "dns/opcode-%s.rrd";
@@ -92,9 +89,7 @@ static char *rcode_ds_def[] =
 };
 static int rcode_ds_num = 1;
 
-/* FIXME: Wouldn't other defines be better? -octo */
-#if NAMED_HAVE_CONFIG
-#if HAVE_LIBPCAP
+#if DNS_HAVE_READ
 static char *config_keys[] =
 {
        "Interface",
@@ -102,10 +97,7 @@ static char *config_keys[] =
        NULL
 };
 static int config_keys_num = 2;
-#endif /* HAVE_LIBPCAP */
-#endif /* NAMED_HAVE_CONFIG */
 
-#if HAVE_LIBPCAP
 #define PCAP_SNAPLEN 1460
 static char   *pcap_device = NULL;
 
@@ -114,9 +106,7 @@ static unsigned int    tr_responses;
 static counter_list_t *qtype_list;
 static counter_list_t *opcode_list;
 static counter_list_t *rcode_list;
-#endif
 
-#if HAVE_PTHREAD_H
 static pthread_t       listen_thread;
 static int             listen_thread_init = 0;
 /* The `traffic' mutex if for `tr_queries' and `tr_responses' */
@@ -124,8 +114,12 @@ static pthread_mutex_t traffic_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t qtype_mutex   = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t opcode_mutex  = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t rcode_mutex   = PTHREAD_MUTEX_INITIALIZER;
-#endif
+#endif /* DNS_HAVE_READ */
 
+/*
+ * Private functions
+ */
+#if DNS_HAVE_READ
 static counter_list_t *counter_list_search (counter_list_t **list, unsigned int key)
 {
        counter_list_t *entry;
@@ -197,10 +191,8 @@ static void counter_list_add (counter_list_t **list,
        DBG ("return ()");
 }
 
-#if NAMED_HAVE_CONFIG
 static int dns_config (char *key, char *value)
 {
-#if HAVE_LIBPCAP
        if (strcasecmp (key, "Interface") == 0)
        {
                if (pcap_device != NULL)
@@ -219,9 +211,7 @@ static int dns_config (char *key, char *value)
        }
 
        return (0);
-#endif /* HAVE_LIBPCAP */
 }
-#endif /* NAMED_HAVE_CONFIG */
 
 static void dns_child_callback (const rfc1035_header_t *dns)
 {
@@ -260,20 +250,21 @@ static void *dns_child_loop (void *dummy)
        char    pcap_error[PCAP_ERRBUF_SIZE];
        struct  bpf_program fp;
 
-       struct pollfd poll_fds[1];
        int status;
 
-       /* Don't catch these signals */
-       /* FIXME: Really? */
-       signal (SIGINT, SIG_DFL);
-       signal (SIGTERM, SIG_DFL);
+       /* Don't block any signals */
+       {
+               sigset_t sigmask;
+               sigemptyset (&sigmask);
+               pthread_sigmask (SIG_SETMASK, &sigmask, NULL);
+       }
 
        /* Passing `pcap_device == NULL' is okay and the same as passign "any" */
        DBG ("Creating PCAP object..");
        pcap_obj = pcap_open_live (pcap_device,
                        PCAP_SNAPLEN,
                        0 /* Not promiscuous */,
-                       0 /* no read timeout */,
+                       atoi (COLLECTD_STEP),
                        pcap_error);
        if (pcap_obj == NULL)
        {
@@ -303,64 +294,27 @@ static void *dns_child_loop (void *dummy)
        dnstop_set_pcap_obj (pcap_obj);
        dnstop_set_callback (dns_child_callback);
 
-       /* Set up poll object */
-       poll_fds[0].fd = pcap_fileno (pcap_obj);
-       poll_fds[0].events = POLLIN | POLLPRI;
-
-       while (42)
-       {
-               DBG ("poll (...)");
-               status = poll (poll_fds, 1, -1 /* wait forever for a change */);
-
-               /* Signals are not caught, but this is very handy when
-                * attaching to the process with a debugger. -octo */
-               if ((status < 0) && (errno == EINTR))
-               {
-                       errno = 0;
-                       continue;
-               }
-
-               if (status < 0)
-               {
-                       syslog (LOG_ERR, "dns plugin: poll(2) failed: %s",
-                                       strerror (errno));
-                       break;
-               }
-
-               if (poll_fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
-               {
-                       DBG ("pcap-device closed. Exiting.");
-                       syslog (LOG_ERR, "dns plugin: pcap-device closed. Exiting.");
-                       break;
-               }
-               else if (poll_fds[0].revents & (POLLIN | POLLPRI))
-               {
-                       status = pcap_dispatch (pcap_obj,
-                                       10 /* Only handle 10 packets at a time */,
-                                       handle_pcap /* callback */,
-                                       NULL /* Whatever this means.. */);
-                       if (status < 0)
-                       {
-                               DBG ("pcap_dispatch failed: %s", pcap_geterr (pcap_obj));
-                               syslog (LOG_ERR, "dns plugin: pcap_dispatch failed: %s",
-                                               pcap_geterr (pcap_obj));
-                               break;
-                       }
-               }
-       } /* while (42) */
+       status = pcap_loop (pcap_obj,
+                       -1 /* loop forever */,
+                       handle_pcap /* callback */,
+                       NULL /* Whatever this means.. */);
+       if (status < 0)
+               syslog (LOG_ERR, "dns plugin: Listener thread is exiting "
+                               "abnormally: %s", pcap_geterr (pcap_obj));
 
        DBG ("child is exiting");
 
        pcap_close (pcap_obj);
+       listen_thread_init = 0;
        pthread_exit (NULL);
 
        return (NULL);
 } /* static void dns_child_loop (void) */
+#endif /* DNS_HAVE_READ */
 
 static void dns_init (void)
 {
-#if HAVE_LIBPCAP
-#if HAVE_PTHREAD_H
+#if DNS_HAVE_READ
        /* clean up an old thread */
        int status;
 
@@ -382,8 +336,7 @@ static void dns_init (void)
        }
 
        listen_thread_init = 1;
-#endif
-#endif
+#endif /* DNS_HAVE_READ */
 }
 
 static void traffic_write (char *host, char *inst, char *val)
@@ -434,6 +387,7 @@ static void opcode_write (char *host, char *inst, char *val)
        rrd_update_file (host, file, val, opcode_ds_def, opcode_ds_num);
 }
 
+#if DNS_HAVE_READ
 static void traffic_submit (unsigned int queries, unsigned int replies)
 {
        char buffer[64];
@@ -494,7 +448,6 @@ static void opcode_submit (int opcode, unsigned int counter)
        plugin_submit ("dns_opcode", inst, buffer);
 }
 
-#if NAMED_HAVE_READ
 static void dns_read (void)
 {
        unsigned int keys[T_MAX];
@@ -558,7 +511,7 @@ static void dns_read (void)
                rcode_submit (keys[i], values[i]);
        }
 }
-#else /* if !NAMED_HAVE_READ */
+#else /* if !DNS_HAVE_READ */
 # define dns_read NULL
 #endif
 
@@ -569,7 +522,9 @@ void module_register (void)
        plugin_register ("dns_qtype", NULL, NULL, qtype_write);
        plugin_register ("dns_rcode", NULL, NULL, rcode_write);
        plugin_register ("dns_opcode", NULL, NULL, opcode_write);
+#if DNS_HAVE_READ
        cf_register (MODULE_NAME, dns_config, config_keys, config_keys_num);
+#endif
 }
 
 #undef MODULE_NAME