X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fdns.c;h=e64af0dd8440ac3bb63c9ae632ecc54404834701;hp=0494b4baeb20494f3a00fdb629eb2d738b637077;hb=1159cb5d383c55a80a0db100b8f7aadcf44740a5;hpb=51181b899668ad2c232a152d6e5e787c4eb049cc diff --git a/src/dns.c b/src/dns.c index 0494b4ba..e64af0dd 100644 --- a/src/dns.c +++ b/src/dns.c @@ -29,449 +29,374 @@ #include "common.h" #include "plugin.h" -#include "utils_dns.h" #include +#include "utils_dns.h" #include #ifdef HAVE_SYS_CAPABILITY_H -# include +#include #endif /* * Private data types */ -struct counter_list_s -{ - unsigned int key; - unsigned int value; - struct counter_list_s *next; +struct counter_list_s { + unsigned int key; + unsigned int value; + struct counter_list_s *next; }; typedef struct counter_list_s counter_list_t; /* * Private variables */ -static const char *config_keys[] = -{ - "Interface", - "IgnoreSource", - "SelectNumericQueryTypes" -}; -static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); +static const char *config_keys[] = {"Interface", "IgnoreSource", + "SelectNumericQueryTypes"}; +static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static int select_numeric_qtype = 1; #define PCAP_SNAPLEN 1460 -static char *pcap_device = NULL; +static char *pcap_device = NULL; -static derive_t tr_queries; -static derive_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; -static pthread_t listen_thread; -static int listen_thread_init = 0; +static pthread_t listen_thread; +static int listen_thread_init = 0; /* The `traffic' mutex if for `tr_queries' and `tr_responses' */ 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; +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; /* * Private functions */ -static counter_list_t *counter_list_search (counter_list_t **list, unsigned int key) -{ - counter_list_t *entry; +static counter_list_t *counter_list_search(counter_list_t **list, + unsigned int key) { + counter_list_t *entry; - for (entry = *list; entry != NULL; entry = entry->next) - if (entry->key == key) - break; + for (entry = *list; entry != NULL; entry = entry->next) + if (entry->key == key) + break; - return (entry); + return entry; } -static counter_list_t *counter_list_create (counter_list_t **list, - unsigned int key, unsigned int value) -{ - counter_list_t *entry; +static counter_list_t *counter_list_create(counter_list_t **list, + unsigned int key, + unsigned int value) { + counter_list_t *entry; - entry = calloc (1, sizeof (*entry)); - if (entry == NULL) - return (NULL); + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + return NULL; - entry->key = key; - entry->value = value; + entry->key = key; + entry->value = value; - if (*list == NULL) - { - *list = entry; - } - else - { - counter_list_t *last; + if (*list == NULL) { + *list = entry; + } else { + counter_list_t *last; - last = *list; - while (last->next != NULL) - last = last->next; + last = *list; + while (last->next != NULL) + last = last->next; - last->next = entry; - } + last->next = entry; + } - return (entry); + return entry; } -static void counter_list_add (counter_list_t **list, - unsigned int key, unsigned int increment) -{ - counter_list_t *entry; - - entry = counter_list_search (list, key); - - if (entry != NULL) - { - entry->value += increment; - } - else - { - counter_list_create (list, key, increment); - } +static void counter_list_add(counter_list_t **list, unsigned int key, + unsigned int increment) { + counter_list_t *entry; + + entry = counter_list_search(list, key); + + if (entry != NULL) { + entry->value += increment; + } else { + counter_list_create(list, key, increment); + } } -static int dns_config (const char *key, const char *value) -{ - if (strcasecmp (key, "Interface") == 0) - { - if (pcap_device != NULL) - free (pcap_device); - if ((pcap_device = strdup (value)) == NULL) - return (1); - } - else if (strcasecmp (key, "IgnoreSource") == 0) - { - if (value != NULL) - ignore_list_add_name (value); - } - else if (strcasecmp (key, "SelectNumericQueryTypes") == 0) - { - if ((value != NULL) && IS_FALSE (value)) - select_numeric_qtype = 0; - else - select_numeric_qtype = 1; - } - else - { - return (-1); - } - - return (0); +static int dns_config(const char *key, const char *value) { + if (strcasecmp(key, "Interface") == 0) { + if (pcap_device != NULL) + free(pcap_device); + if ((pcap_device = strdup(value)) == NULL) + return 1; + } else if (strcasecmp(key, "IgnoreSource") == 0) { + if (value != NULL) + ignore_list_add_name(value); + } else if (strcasecmp(key, "SelectNumericQueryTypes") == 0) { + if ((value != NULL) && IS_FALSE(value)) + select_numeric_qtype = 0; + else + select_numeric_qtype = 1; + } else { + return -1; + } + + return 0; } -static void dns_child_callback (const rfc1035_header_t *dns) -{ - if (dns->qr == 0) - { - /* This is a query */ - int skip = 0; - if (!select_numeric_qtype) - { - const char *str = qtype_str(dns->qtype); - if ((str == NULL) || (str[0] == '#')) - skip = 1; - } - - pthread_mutex_lock (&traffic_mutex); - tr_queries += dns->length; - pthread_mutex_unlock (&traffic_mutex); - - if (skip == 0) - { - pthread_mutex_lock (&qtype_mutex); - counter_list_add (&qtype_list, dns->qtype, 1); - pthread_mutex_unlock (&qtype_mutex); - } - } - else - { - /* This is a reply */ - pthread_mutex_lock (&traffic_mutex); - tr_responses += dns->length; - pthread_mutex_unlock (&traffic_mutex); - - pthread_mutex_lock (&rcode_mutex); - counter_list_add (&rcode_list, dns->rcode, 1); - pthread_mutex_unlock (&rcode_mutex); - } - - /* FIXME: Are queries, replies or both interesting? */ - pthread_mutex_lock (&opcode_mutex); - counter_list_add (&opcode_list, dns->opcode, 1); - pthread_mutex_unlock (&opcode_mutex); +static void dns_child_callback(const rfc1035_header_t *dns) { + if (dns->qr == 0) { + /* This is a query */ + int skip = 0; + if (!select_numeric_qtype) { + const char *str = qtype_str(dns->qtype); + if ((str == NULL) || (str[0] == '#')) + skip = 1; + } + + pthread_mutex_lock(&traffic_mutex); + tr_queries += dns->length; + pthread_mutex_unlock(&traffic_mutex); + + if (skip == 0) { + pthread_mutex_lock(&qtype_mutex); + counter_list_add(&qtype_list, dns->qtype, 1); + pthread_mutex_unlock(&qtype_mutex); + } + } else { + /* This is a reply */ + pthread_mutex_lock(&traffic_mutex); + tr_responses += dns->length; + pthread_mutex_unlock(&traffic_mutex); + + pthread_mutex_lock(&rcode_mutex); + counter_list_add(&rcode_list, dns->rcode, 1); + pthread_mutex_unlock(&rcode_mutex); + } + + /* FIXME: Are queries, replies or both interesting? */ + pthread_mutex_lock(&opcode_mutex); + counter_list_add(&opcode_list, dns->opcode, 1); + pthread_mutex_unlock(&opcode_mutex); } -static int dns_run_pcap_loop (void) -{ - pcap_t *pcap_obj; - char pcap_error[PCAP_ERRBUF_SIZE]; - struct bpf_program fp = { 0 }; - - int status; - - /* 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" */ - DEBUG ("dns plugin: Creating PCAP object.."); - pcap_obj = pcap_open_live ((pcap_device != NULL) ? pcap_device : "any", - PCAP_SNAPLEN, - 0 /* Not promiscuous */, - (int) CDTIME_T_TO_MS (plugin_get_interval () / 2), - pcap_error); - if (pcap_obj == NULL) - { - ERROR ("dns plugin: Opening interface `%s' " - "failed: %s", - (pcap_device != NULL) ? pcap_device : "any", - pcap_error); - return (PCAP_ERROR); - } - - status = pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0); - if (status < 0) - { - ERROR ("dns plugin: pcap_compile failed: %s", - pcap_statustostr (status)); - return (status); - } - - status = pcap_setfilter (pcap_obj, &fp); - if (status < 0) - { - ERROR ("dns plugin: pcap_setfilter failed: %s", - pcap_statustostr (status)); - return (status); - } - - DEBUG ("dns plugin: PCAP object created."); - - dnstop_set_pcap_obj (pcap_obj); - dnstop_set_callback (dns_child_callback); - - status = pcap_loop (pcap_obj, - -1 /* loop forever */, - handle_pcap /* callback */, - 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); - return (status); +static int dns_run_pcap_loop(void) { + pcap_t *pcap_obj; + char pcap_error[PCAP_ERRBUF_SIZE]; + struct bpf_program fp = {0}; + + int status; + + /* 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" */ + DEBUG("dns plugin: Creating PCAP object.."); + pcap_obj = pcap_open_live((pcap_device != NULL) ? pcap_device : "any", + PCAP_SNAPLEN, 0 /* Not promiscuous */, + (int)CDTIME_T_TO_MS(plugin_get_interval() / 2), + pcap_error); + if (pcap_obj == NULL) { + ERROR("dns plugin: Opening interface `%s' " + "failed: %s", + (pcap_device != NULL) ? pcap_device : "any", pcap_error); + return PCAP_ERROR; + } + + status = pcap_compile(pcap_obj, &fp, "udp port 53", 1, 0); + if (status < 0) { + ERROR("dns plugin: pcap_compile failed: %s", pcap_statustostr(status)); + return status; + } + + status = pcap_setfilter(pcap_obj, &fp); + if (status < 0) { + ERROR("dns plugin: pcap_setfilter failed: %s", pcap_statustostr(status)); + return status; + } + + DEBUG("dns plugin: PCAP object created."); + + dnstop_set_pcap_obj(pcap_obj); + dnstop_set_callback(dns_child_callback); + + status = pcap_loop(pcap_obj, -1 /* loop forever */, + handle_pcap /* callback */, 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); + return status; } /* int dns_run_pcap_loop */ -static int dns_sleep_one_interval (void) /* {{{ */ +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); + struct timespec ts = CDTIME_T_TO_TIMESPEC(plugin_get_interval()); + while (nanosleep(&ts, &ts) != 0) { + if ((errno == EINTR) || (errno == EAGAIN)) + continue; + + return errno; + } + + return 0; } /* }}} int dns_sleep_one_interval */ -static void *dns_child_loop (__attribute__((unused)) void *dummy) /* {{{ */ +static void *dns_child_loop(__attribute__((unused)) void *dummy) /* {{{ */ { - int status; + int status; - while (42) - { - status = dns_run_pcap_loop (); - if (status != PCAP_ERROR_IFACE_NOT_UP) - break; + while (42) { + status = dns_run_pcap_loop(); + if (status != PCAP_ERROR_IFACE_NOT_UP) + break; - dns_sleep_one_interval (); - } + dns_sleep_one_interval(); + } - if (status != PCAP_ERROR_BREAK) - ERROR ("dns plugin: PCAP returned error %s.", - pcap_statustostr (status)); + if (status != PCAP_ERROR_BREAK) + ERROR("dns plugin: PCAP returned error %s.", pcap_statustostr(status)); - listen_thread_init = 0; - return (NULL); + listen_thread_init = 0; + return NULL; } /* }}} void *dns_child_loop */ -static int dns_init (void) -{ - /* clean up an old thread */ - int status; +static int dns_init(void) { + /* clean up an old thread */ + int status; - pthread_mutex_lock (&traffic_mutex); - tr_queries = 0; - tr_responses = 0; - pthread_mutex_unlock (&traffic_mutex); + pthread_mutex_lock(&traffic_mutex); + tr_queries = 0; + tr_responses = 0; + pthread_mutex_unlock(&traffic_mutex); - if (listen_thread_init != 0) - return (-1); + if (listen_thread_init != 0) + return -1; - status = plugin_thread_create (&listen_thread, NULL, dns_child_loop, - (void *) 0); - if (status != 0) - { - char errbuf[1024]; - ERROR ("dns plugin: pthread_create failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); - } + status = plugin_thread_create(&listen_thread, NULL, dns_child_loop, (void *)0, + "dns listen"); + if (status != 0) { + char errbuf[1024]; + ERROR("dns plugin: pthread_create failed: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } - listen_thread_init = 1; + listen_thread_init = 1; #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW) - if (check_capability (CAP_NET_RAW) != 0) - { - if (getuid () == 0) - WARNING ("dns plugin: Running collectd as root, but the CAP_NET_RAW " - "capability is missing. The plugin's read function will probably " - "fail. Is your init system dropping capabilities?"); - else - WARNING ("dns plugin: collectd doesn't have the CAP_NET_RAW capability. " - "If you don't want to run collectd as root, try running \"setcap " - "cap_net_raw=ep\" on the collectd binary."); - } + if (check_capability(CAP_NET_RAW) != 0) { + if (getuid() == 0) + WARNING("dns plugin: Running collectd as root, but the CAP_NET_RAW " + "capability is missing. The plugin's read function will probably " + "fail. Is your init system dropping capabilities?"); + else + WARNING("dns plugin: collectd doesn't have the CAP_NET_RAW capability. " + "If you don't want to run collectd as root, try running \"setcap " + "cap_net_raw=ep\" on the collectd binary."); + } #endif - return (0); + return 0; } /* int dns_init */ -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; +static void submit_derive(const char *type, const char *type_instance, + derive_t value) { + value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; + vl.values = &(value_t){.derive = value}; + vl.values_len = 1; + sstrncpy(vl.plugin, "dns", sizeof(vl.plugin)); + sstrncpy(vl.type, type, sizeof(vl.type)); + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - vl.values = values; - vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "dns", sizeof (vl.plugin)); - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } /* void submit_derive */ -static void submit_octets (derive_t queries, derive_t responses) -{ - value_t values[2]; - value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = queries; - values[1].derive = responses; +static void submit_octets(derive_t queries, derive_t responses) { + value_t values[] = { + {.derive = queries}, {.derive = responses}, + }; + value_list_t vl = VALUE_LIST_INIT; - vl.values = values; - vl.values_len = 2; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "dns", sizeof (vl.plugin)); - sstrncpy (vl.type, "dns_octets", sizeof (vl.type)); + vl.values = values; + vl.values_len = STATIC_ARRAY_SIZE(values); + sstrncpy(vl.plugin, "dns", sizeof(vl.plugin)); + sstrncpy(vl.type, "dns_octets", sizeof(vl.type)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } /* void submit_octets */ -static int dns_read (void) -{ - unsigned int keys[T_MAX]; - unsigned int values[T_MAX]; - int len; - - counter_list_t *ptr; - - pthread_mutex_lock (&traffic_mutex); - values[0] = tr_queries; - values[1] = tr_responses; - pthread_mutex_unlock (&traffic_mutex); - - if ((values[0] != 0) || (values[1] != 0)) - submit_octets (values[0], values[1]); - - pthread_mutex_lock (&qtype_mutex); - for (ptr = qtype_list, len = 0; - (ptr != NULL) && (len < T_MAX); - ptr = ptr->next, len++) - { - keys[len] = ptr->key; - values[len] = ptr->value; - } - pthread_mutex_unlock (&qtype_mutex); - - for (int i = 0; i < len; 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); - for (ptr = opcode_list, len = 0; - (ptr != NULL) && (len < T_MAX); - ptr = ptr->next, len++) - { - keys[len] = ptr->key; - values[len] = ptr->value; - } - pthread_mutex_unlock (&opcode_mutex); - - for (int i = 0; i < len; 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); - for (ptr = rcode_list, len = 0; - (ptr != NULL) && (len < T_MAX); - ptr = ptr->next, len++) - { - keys[len] = ptr->key; - values[len] = ptr->value; - } - pthread_mutex_unlock (&rcode_mutex); - - for (int i = 0; i < len; i++) - { - DEBUG ("dns plugin: rcode = %u; counter = %u;", keys[i], values[i]); - submit_derive ("dns_rcode", rcode_str (keys[i]), values[i]); - } - - return (0); +static int dns_read(void) { + unsigned int keys[T_MAX]; + unsigned int values[T_MAX]; + int len; + + counter_list_t *ptr; + + pthread_mutex_lock(&traffic_mutex); + values[0] = tr_queries; + values[1] = tr_responses; + pthread_mutex_unlock(&traffic_mutex); + + if ((values[0] != 0) || (values[1] != 0)) + submit_octets(values[0], values[1]); + + pthread_mutex_lock(&qtype_mutex); + for (ptr = qtype_list, len = 0; (ptr != NULL) && (len < T_MAX); + ptr = ptr->next, len++) { + keys[len] = ptr->key; + values[len] = ptr->value; + } + pthread_mutex_unlock(&qtype_mutex); + + for (int i = 0; i < len; 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); + for (ptr = opcode_list, len = 0; (ptr != NULL) && (len < T_MAX); + ptr = ptr->next, len++) { + keys[len] = ptr->key; + values[len] = ptr->value; + } + pthread_mutex_unlock(&opcode_mutex); + + for (int i = 0; i < len; 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); + for (ptr = rcode_list, len = 0; (ptr != NULL) && (len < T_MAX); + ptr = ptr->next, len++) { + keys[len] = ptr->key; + values[len] = ptr->value; + } + pthread_mutex_unlock(&rcode_mutex); + + for (int i = 0; i < len; i++) { + DEBUG("dns plugin: rcode = %u; counter = %u;", keys[i], values[i]); + submit_derive("dns_rcode", rcode_str(keys[i]), values[i]); + } + + return 0; } /* int dns_read */ -void module_register (void) -{ - plugin_register_config ("dns", dns_config, config_keys, config_keys_num); - plugin_register_init ("dns", dns_init); - plugin_register_read ("dns", dns_read); +void module_register(void) { + plugin_register_config("dns", dns_config, config_keys, config_keys_num); + plugin_register_init("dns", dns_init); + plugin_register_read("dns", dns_read); } /* void module_register */