dns plugin: Corrected the handling of signals, i. e. don't catch them.
[collectd.git] / src / dns.c
index 15afef9..b97ce28 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -53,10 +53,20 @@ struct counter_list_s
 };
 typedef struct counter_list_s counter_list_t;
 
+static char *traffic_file   = "dns/dns_traffic.rrd";
 static char *qtype_file   = "dns/qtype-%s.rrd";
 static char *opcode_file  = "dns/opcode-%s.rrd";
 static char *rcode_file   = "dns/rcode-%s.rrd";
 
+static char *traffic_ds_def[] =
+{
+       /* Limit to 1GBit/s */
+       "DS:queries:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
+       "DS:responses:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
+       NULL
+};
+static int traffic_ds_num = 2;
+
 static char *qtype_ds_def[] =
 {
        "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
@@ -95,6 +105,8 @@ static int config_keys_num = 2;
 static char   *pcap_device = NULL;
 static int     pipe_fd = -1;
 
+static unsigned int    tr_queries;
+static unsigned int    tr_responses;
 static counter_list_t *qtype_list;
 static counter_list_t *opcode_list;
 static counter_list_t *rcode_list;
@@ -246,11 +258,13 @@ static void dns_child_callback (const rfc1035_header_t *dns)
        if (dns->qr == 0)
        {
                /* This is a query */
+               tr_queries += dns->length;
                counter_list_add (&qtype_list,  dns->qtype,  1);
        }
        else
        {
                /* This is a reply */
+               tr_responses += dns->length;
                counter_list_add (&rcode_list,  dns->rcode,  1);
        }
 
@@ -267,6 +281,10 @@ static void dns_child_loop (void)
        struct pollfd poll_fds[2];
        int status;
 
+       /* Don't catch these signals */
+       signal (SIGINT, SIG_DFL);
+       signal (SIGTERM, SIG_DFL);
+
        /* Passing `pcap_device == NULL' is okay and the same as passign "any" */
        DBG ("Creating PCAP object..");
        pcap_obj = pcap_open_live (pcap_device,
@@ -320,6 +338,14 @@ static void dns_child_loop (void)
                DBG ("poll (...)");
                status = poll (poll_fds, 2, -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",
@@ -336,6 +362,25 @@ static void dns_child_loop (void)
                else if (poll_fds[0].revents & POLLOUT)
                {
                        DBG ("Sending data..");
+
+                       DBG ("swrite (pipe_fd = %i, tr_queries = %i)", pipe_fd, tr_queries);
+                       if (swrite (pipe_fd, (const void *) &tr_queries, sizeof (tr_queries)) != 0)
+                       {
+                               DBG ("Writing to pipe_fd failed: %s", strerror (errno));
+                               syslog (LOG_ERR, "dns plugin: Writing to pipe_fd failed: %s",
+                                               strerror (errno));
+                               return;
+                       }
+
+                       DBG ("swrite (pipe_fd = %i, tr_responses = %i)", pipe_fd, tr_responses);
+                       if (swrite (pipe_fd, (const void *) &tr_responses, sizeof (tr_responses)) != 0)
+                       {
+                               DBG ("Writing to pipe_fd failed: %s", strerror (errno));
+                               syslog (LOG_ERR, "dns plugin: Writing to pipe_fd failed: %s",
+                                               strerror (errno));
+                               return;
+                       }
+
                        counter_list_send (qtype_list, pipe_fd);
                        counter_list_send (opcode_list, pipe_fd);
                        counter_list_send (rcode_list, pipe_fd);
@@ -376,6 +421,9 @@ static void dns_init (void)
        int pipe_fds[2];
        pid_t pid_child;
 
+       tr_queries   = 0;
+       tr_responses = 0;
+
        if (pipe (pipe_fds) != 0)
        {
                syslog (LOG_ERR, "dns plugin: pipe(2) failed: %s",
@@ -413,6 +461,12 @@ static void dns_init (void)
 #endif
 }
 
+static void traffic_write (char *host, char *inst, char *val)
+{
+       rrd_update_file (host, traffic_file, val,
+                       traffic_ds_def, traffic_ds_num);
+}
+
 static void qtype_write (char *host, char *inst, char *val)
 {
        char file[512];
@@ -455,6 +509,18 @@ static void opcode_write (char *host, char *inst, char *val)
        rrd_update_file (host, file, val, opcode_ds_def, opcode_ds_num);
 }
 
+static void traffic_submit (unsigned int queries, unsigned int replies)
+{
+       char buffer[64];
+       int  status;
+
+       status = snprintf (buffer, 64, "N:%u:%u", queries, replies);
+       if ((status < 1) || (status >= 64))
+               return;
+
+       plugin_submit ("dns_traffic", "-", buffer);
+}
+
 static void qtype_submit (int qtype, unsigned int counter)
 {
        char inst[32];
@@ -549,6 +615,30 @@ static void dns_read (void)
        if (pipe_fd < 0)
                return;
 
+       if (sread (pipe_fd, (void *) &tr_queries, sizeof (tr_queries)) != 0)
+       {
+               DBG ("Reading from the pipe failed: %s",
+                               strerror (errno));
+               syslog (LOG_ERR, "dns plugin: Reading from the pipe failed: %s",
+                               strerror (errno));
+               pipe_fd = -1;
+               return;
+       }
+       DBG ("sread (pipe_fd = %i, tr_queries = %u)", pipe_fd, tr_queries);
+
+       if (sread (pipe_fd, (void *) &tr_responses, sizeof (tr_responses)) != 0)
+       {
+               DBG ("Reading from the pipe failed: %s",
+                               strerror (errno));
+               syslog (LOG_ERR, "dns plugin: Reading from the pipe failed: %s",
+                               strerror (errno));
+               pipe_fd = -1;
+               return;
+       }
+       DBG ("sread (pipe_fd = %i, tr_responses = %u)", pipe_fd, tr_responses);
+
+       traffic_submit (tr_queries, tr_responses);
+
        values_num = dns_read_array (values);
        for (i = 0; i < values_num; i++)
        {
@@ -577,6 +667,7 @@ static void dns_read (void)
 void module_register (void)
 {
        plugin_register (MODULE_NAME, dns_init, dns_read, NULL);
+       plugin_register ("dns_traffic", NULL, NULL, traffic_write);
        plugin_register ("dns_qtype", NULL, NULL, qtype_write);
        plugin_register ("dns_rcode", NULL, NULL, rcode_write);
        plugin_register ("dns_opcode", NULL, NULL, opcode_write);