2 * collectd - src/named.c
3 * Copyright (C) 2006 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Florian octo Forster <octo at verplant.org>
26 #include "configfile.h"
27 #include "utils_debug.h"
30 # include <sys/poll.h>
33 #define MODULE_NAME "named"
36 # define NAMED_HAVE_CONFIG 1
38 # define NAMED_HAVE_CONFIG 0
43 # define NAMED_HAVE_READ 1
45 # define NAMED_HAVE_READ 0
48 static char *qtype_file = "named/qtype-%s.rrd";
50 static char *qtype_ds_def[] =
52 "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
55 static int qtype_ds_num = 1;
59 static char *config_keys[] =
64 static int config_keys_num = 1;
65 #endif /* HAVE_LIBPCAP */
66 #endif /* NAMED_HAVE_CONFIG */
69 #define PCAP_SNAPLEN 1460
70 static char *pcap_device = NULL;
71 static int pipe_fd = -1;
75 static int named_config (char *key, char *value)
78 if (strcasecmp (key, "Interface") == 0)
80 if (pcap_device != NULL)
82 if ((pcap_device = strdup (value)) == NULL)
91 #endif /* HAVE_LIBPCAP */
93 #endif /* NAMED_HAVE_CONFIG */
95 static int named_child_send_data (void)
97 int values[2 * T_MAX];
105 for (i = 0; i < T_MAX; i++)
107 if (qtype_counts[i] != 0)
109 values[2 * values_num] = i;
110 values[(2 * values_num) + 1] = qtype_counts[i];
115 DBG ("swrite (pipe_fd = %i, values_num = %i)", pipe_fd, values_num);
116 if (swrite (pipe_fd, (const void *) &values_num, sizeof (values_num)) != 0)
118 DBG ("Writing to pipe failed: %s", strerror (errno));
119 syslog (LOG_ERR, "named plugin: Writing to pipe failed: %s",
127 DBG ("swrite (pipe_fd = %i, values = %p, size = %i)", pipe_fd, (void *) values, (int) (sizeof (int) * values_num));
128 if (swrite (pipe_fd, (const void *) values, 2 * sizeof (int) * values_num) != 0)
130 DBG ("Writing to pipe failed: %s", strerror (errno));
131 syslog (LOG_ERR, "named plugin: Writing to pipe failed: %s",
139 static void named_child_loop (void)
142 char pcap_error[PCAP_ERRBUF_SIZE];
143 struct bpf_program fp;
145 struct pollfd poll_fds[2];
148 /* Passing `pcap_device == NULL' is okay and the same as passign "any" */
149 DBG ("Creating PCAP object..");
150 pcap_obj = pcap_open_live (pcap_device,
152 0 /* Not promiscuous */,
153 0 /* no read timeout */,
155 if (pcap_obj == NULL)
157 syslog (LOG_ERR, "named plugin: Opening interface `%s' failed: %s",
158 (pcap_device != NULL) ? pcap_device : "any",
164 pcap = pcap_obj; /* FIXME: This is used by `handle_pcap' */
166 memset (&fp, 0, sizeof (fp));
167 if (pcap_compile (pcap_obj, &fp, "udp dst port 53", 1, 0) < 0)
169 DBG ("pcap_compile failed");
170 syslog (LOG_ERR, "named plugin: pcap_compile failed");
175 if (pcap_setfilter (pcap_obj, &fp) < 0)
177 DBG ("pcap_setfilter failed");
178 syslog (LOG_ERR, "named plugin: pcap_setfilter failed");
184 DBG ("PCAP object created.");
186 /* Set up pipe end */
187 poll_fds[0].fd = pipe_fd;
188 poll_fds[0].events = POLLOUT;
190 /* Set up pcap device */
191 poll_fds[1].fd = pcap_fileno (pcap_obj);
192 poll_fds[1].events = POLLIN | POLLPRI;
197 status = poll (poll_fds, 2, -1 /* wait forever for a change */);
201 syslog (LOG_ERR, "named plugin: poll(2) failed: %s",
206 if (poll_fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
208 DBG ("Pipe closed. Exiting.");
209 syslog (LOG_NOTICE, "named plugin: Pipe closed. Exiting.");
212 else if (poll_fds[0].revents & POLLOUT)
214 DBG ("Calling `named_child_send_data'");
215 if (named_child_send_data () < 0)
221 if (poll_fds[1].revents & (POLLERR | POLLHUP | POLLNVAL))
223 DBG ("pcap-device closed. Exiting.");
224 syslog (LOG_ERR, "named plugin: pcap-device closed. Exiting.");
227 else if (poll_fds[1].revents & (POLLIN | POLLPRI))
229 /* TODO: Read and analyse packet */
230 status = pcap_dispatch (pcap_obj,
231 1 /* Only handle 10 packets at a time */,
232 handle_pcap /* callback */,
233 NULL /* Whatever this means.. */);
236 DBG ("pcap_dispatch failed: %s", pcap_geterr (pcap_obj));
237 syslog (LOG_ERR, "named plugin: pcap_dispatch failed: %s",
238 pcap_geterr (pcap_obj));
244 DBG ("child is exiting");
248 pcap_close (pcap_obj);
249 } /* static void named_child_loop (void) */
251 static void named_init (void)
257 if (pipe (pipe_fds) != 0)
259 syslog (LOG_ERR, "named plugin: pipe(2) failed: %s",
268 syslog (LOG_ERR, "named plugin: fork(2) failed: %s",
274 else if (pid_child != 0)
276 /* parent: Close the writing end, keep the reading end. */
277 pipe_fd = pipe_fds[0];
282 /* child: Close the reading end, keep the writing end. */
283 pipe_fd = pipe_fds[1];
290 /* fcntl (pipe_fd, F_SETFL, O_NONBLOCK); */
294 static void qtype_write (char *host, char *inst, char *val)
299 status = snprintf (file, 512, qtype_file, inst);
302 else if (status >= 512)
305 rrd_update_file (host, file, val, qtype_ds_def, qtype_ds_num);
308 static void qtype_submit (int qtype_int, unsigned int counter)
314 qtype_char = qtype_str (qtype_int);
316 status = snprintf (buffer, 32, "N:%i", counter);
317 if ((status < 1) || (status >= 32))
320 plugin_submit ("named_qtype", qtype_char, buffer);
324 static void named_read (void)
326 int values[2 * T_MAX];
335 DBG ("Reading from pipe_fd = %i..", pipe_fd);
336 if (sread (pipe_fd, (void *) &values_num, sizeof (values_num)) != 0)
338 syslog (LOG_ERR, "named plugin: Reading from the pipe failed: %s",
344 assert ((values_num >= 0) && (values_num <= T_MAX));
348 DBG ("No values available; returning");
352 DBG ("Reading %i qtype/values from pipe_fd = %i..", values_num, pipe_fd);
353 if (sread (pipe_fd, (void *) values, 2 * sizeof (int) * values_num) != 0)
355 syslog (LOG_ERR, "named plugin: Reading from the pipe failed: %s",
361 for (i = 0; i < values_num; i++)
363 qtype = values[2 * i];
364 counter = values[(2 * i) + 1];
366 DBG ("qtype = %i; counter = %i;", qtype, counter);
367 qtype_submit (qtype, counter);
370 #else /* if !NAMED_HAVE_READ */
371 # define named_read NULL
374 void module_register (void)
376 plugin_register (MODULE_NAME, named_init, named_read, NULL);
377 plugin_register ("named_qtype", NULL, NULL, qtype_write);
379 cf_register (MODULE_NAME, named_config, config_keys, config_keys_num);