X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fpowerdns.c;h=a1b23555bec080592a261f91e1d6e02ae769bd6a;hb=2f2744072ab144b8130b2296327fc3382e5f7f80;hp=06d8d2ef3b45c471ae6f2a392026b48132453a56;hpb=ad8739289d8f254545f3426ec3a34ef30594db7c;p=collectd.git diff --git a/src/powerdns.c b/src/powerdns.c index 06d8d2ef..a1b23555 100644 --- a/src/powerdns.c +++ b/src/powerdns.c @@ -45,20 +45,13 @@ #endif #define FUNC_ERROR(func) do { char errbuf[1024]; ERROR ("powerdns plugin: %s failed: %s", func, sstrerror (errno, errbuf, sizeof (errbuf))); } while (0) -#define SERVER_SOCKET "/var/run/pdns.controlsocket" -#define SERVER_COMMAND "SHOW *" - -#define RECURSOR_SOCKET "/var/run/pdns_recursor.controlsocket" -#define RECURSOR_COMMAND "get all-outqueries answers0-1 " /* {{{ */ \ - "answers100-1000 answers10-100 answers1-10 answers-slow cache-entries " \ - "cache-hits cache-misses chain-resends client-parse-errors " \ - "concurrent-queries dlg-only-drops ipv6-outqueries negcache-entries " \ - "noerror-answers nsset-invalidations nsspeeds-entries nxdomain-answers " \ - "outgoing-timeouts qa-latency questions resource-limits " \ - "server-parse-errors servfail-answers spoof-prevents sys-msec " \ - "tcp-client-overflow tcp-outqueries tcp-questions throttled-out " \ - "throttled-outqueries throttle-entries unauthorized-tcp unauthorized-udp " \ - "unexpected-packets unreachables user-msec" /* }}} */ +#define SERVER_SOCKET LOCALSTATEDIR"/run/pdns.controlsocket" +#define SERVER_COMMAND "SHOW * \n" + +#define RECURSOR_SOCKET LOCALSTATEDIR"/run/pdns_recursor.controlsocket" +#define RECURSOR_COMMAND "get noerror-answers nxdomain-answers " \ + "servfail-answers sys-msec user-msec qa-latency cache-entries cache-hits " \ + "cache-misses questions\n" struct list_item_s; typedef struct list_item_s list_item_t; @@ -67,7 +60,7 @@ struct list_item_s { enum { - SRV_AUTHORATIVE, + SRV_AUTHORITATIVE, SRV_RECURSOR } server_type; int (*func) (list_item_t *item); @@ -128,6 +121,23 @@ uptime number of seconds process has been running (since 3.1.5) user-msec number of CPU milliseconds spent in 'user' mode }}} */ +const char* const default_server_fields[] = /* {{{ */ +{ + "latency" + "packetcache-hit", + "packetcache-miss", + "packetcache-size", + "query-cache-hit", + "query-cache-miss", + "recursing-answers", + "recursing-questions", + "tcp-answers", + "tcp-queries", + "udp-answers", + "udp-queries", +}; /* }}} */ +int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields); + statname_lookup_t lookup_table[] = /* {{{ */ { /********************* @@ -154,13 +164,13 @@ statname_lookup_t lookup_table[] = /* {{{ */ {"latency", "latency", NULL}, /* Other stuff.. */ - {"corrupt-packets", "io_packets", "corrupt"}, + {"corrupt-packets", "ipt_packets", "corrupt"}, {"deferred-cache-inserts", "counter", "cache-deferred_insert"}, {"deferred-cache-lookup", "counter", "cache-deferred_lookup"}, {"qsize-a", "cache_size", "answers"}, {"qsize-q", "cache_size", "questions"}, - {"servfail-packets", "io_packets", "servfail"}, - {"timedout-packets", "io_packets", "timeout"}, + {"servfail-packets", "ipt_packets", "servfail"}, + {"timedout-packets", "ipt_packets", "timeout"}, {"udp4-answers", "dns_answer", "udp4"}, {"udp4-queries", "dns_question", "queries-udp4"}, {"udp6-answers", "dns_answer", "udp6"}, @@ -254,7 +264,7 @@ static void submit (const char *plugin_instance, /* {{{ */ if (i >= lookup_table_length) { - DEBUG ("powerdns plugin: submit: Not found in lookup table: %s = %s;", + INFO ("powerdns plugin: submit: Not found in lookup table: %s = %s;", pdns_type, value); return; } @@ -279,42 +289,23 @@ static void submit (const char *plugin_instance, /* {{{ */ return; } - if (ds->ds[0].type == DS_TYPE_GAUGE) + if (0 != parse_value (value, &values[0], ds->ds[0].type)) { - char *endptr = NULL; - - values[0].gauge = strtod (value, &endptr); - - if (endptr == value) - { - ERROR ("powerdns plugin: Cannot convert `%s' " - "to a floating point number.", value); - return; - } - } - else - { - char *endptr = NULL; - - values[0].counter = strtoll (value, &endptr, 0); - if (endptr == value) - { - ERROR ("powerdns plugin: Cannot convert `%s' " - "to an integer number.", value); - return; - } + ERROR ("powerdns plugin: Cannot convert `%s' " + "to a number.", value); + return; } vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin)); + sstrncpy (vl.type, type, sizeof (vl.type)); if (type_instance != NULL) sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); - plugin_dispatch_values (type, &vl); + plugin_dispatch_values (&vl); } /* }}} static void submit */ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ @@ -330,6 +321,9 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ struct sockaddr_un sa_unix; + struct timeval stv_timeout; + cdtime_t cdt_timeout; + sd = socket (PF_UNIX, item->socktype, 0); if (sd < 0) { @@ -339,10 +333,9 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ memset (&sa_unix, 0, sizeof (sa_unix)); sa_unix.sun_family = AF_UNIX; - strncpy (sa_unix.sun_path, + sstrncpy (sa_unix.sun_path, (local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH, sizeof (sa_unix.sun_path)); - sa_unix.sun_path[sizeof (sa_unix.sun_path) - 1] = 0; status = unlink (sa_unix.sun_path); if ((status != 0) && (errno != ENOENT)) @@ -371,6 +364,19 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ break; } + cdt_timeout = interval_g * 3 / 4; + if (cdt_timeout < TIME_T_TO_CDTIME_T (2)) + cdt_timeout = TIME_T_TO_CDTIME_T (2); + + CDTIME_T_TO_TIMEVAL (cdt_timeout, &stv_timeout); + + status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &stv_timeout, sizeof (stv_timeout)); + if (status != 0) + { + FUNC_ERROR ("setsockopt"); + break; + } + status = connect (sd, (struct sockaddr *) &item->sockaddr, sizeof (item->sockaddr)); if (status != 0) @@ -392,6 +398,7 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ FUNC_ERROR ("recv"); break; } + buffer_size = status + 1; status = 0; } while (0); @@ -401,7 +408,7 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ if (status != 0) return (-1); - buffer_size = status + 1; + assert (buffer_size > 0); buffer = (char *) malloc (buffer_size); if (buffer == NULL) { @@ -409,8 +416,8 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ return (-1); } - memcpy (buffer, temp, status); - buffer[status] = 0; + memcpy (buffer, temp, buffer_size - 1); + buffer[buffer_size - 1] = 0; *ret_buffer = buffer; *ret_buffer_size = buffer_size; @@ -436,6 +443,11 @@ static int powerdns_get_data_stream (list_item_t *item, /* {{{ */ return (-1); } + struct timeval timeout; + timeout.tv_sec=5; + timeout.tv_usec=0; + status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout)); + status = connect (sd, (struct sockaddr *) &item->sockaddr, sizeof (item->sockaddr)); if (status != 0) @@ -524,8 +536,11 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */ char *key; char *value; + const char* const *fields; + int fields_num; + if (item->command == NULL) - item->command = strdup ("SHOW *"); + item->command = strdup (SERVER_COMMAND); if (item->command == NULL) { ERROR ("powerdns plugin: strdup failed."); @@ -536,6 +551,20 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */ if (status != 0) return (-1); + if (item->fields_num != 0) + { + fields = (const char* const *) item->fields; + fields_num = item->fields_num; + } + else + { + fields = default_server_fields; + fields_num = default_server_fields_num; + } + + assert (fields != NULL); + assert (fields_num > 0); + /* corrupt-packets=0,deferred-cache-inserts=0,deferred-cache-lookup=0,latency=0,packetcache-hit=0,packetcache-miss=0,packetcache-size=0,qsize-q=0,query-cache-hit=0,query-cache-miss=0,recursing-answers=0,recursing-questions=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,udp4-answers=0,udp4-queries=0,udp6-answers=0,udp6-queries=0, */ dummy = buffer; saveptr = NULL; @@ -556,10 +585,10 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */ continue; /* Check if this item was requested. */ - for (i = 0; i < item->fields_num; i++) - if (strcasecmp (key, item->fields[i]) == 0) + for (i = 0; i < fields_num; i++) + if (strcasecmp (key, fields[i]) == 0) break; - if (i >= item->fields_num) + if (i >= fields_num) continue; submit (item->instance, key, value); @@ -582,19 +611,35 @@ static int powerdns_update_recursor_command (list_item_t *li) /* {{{ */ char buffer[4096]; int status; - if (li != NULL) + if (li == NULL) return (0); - strcpy (buffer, "get "); - status = strjoin (&buffer[4], sizeof (buffer) - strlen ("get "), - li->fields, li->fields_num, - /* seperator = */ " "); - if (status < 0) + if (li->fields_num < 1) { - ERROR ("powerdns plugin: strjoin failed."); - return (-1); + sstrncpy (buffer, RECURSOR_COMMAND, sizeof (buffer)); + } + else + { + sstrncpy (buffer, "get ", sizeof (buffer)); + status = strjoin (&buffer[strlen("get ")], sizeof (buffer) - strlen ("get "), + li->fields, li->fields_num, + /* seperator = */ " "); + if (status < 0) + { + ERROR ("powerdns plugin: strjoin failed."); + return (-1); + } + buffer[sizeof (buffer) - 1] = 0; + int i = strlen (buffer); + if (i < sizeof (buffer) - 2) + { + buffer[i++] = ' '; + buffer[i++] = '\n'; + buffer[i++] = '\0'; + } } + buffer[sizeof (buffer) - 1] = 0; li->command = strdup (buffer); if (li->command == NULL) { @@ -627,12 +672,18 @@ static int powerdns_read_recursor (list_item_t *item) /* {{{ */ ERROR ("powerdns plugin: powerdns_update_recursor_command failed."); return (-1); } + + DEBUG ("powerdns plugin: powerdns_read_recursor: item->command = %s;", + item->command); } assert (item->command != NULL); status = powerdns_get_data (item, &buffer, &buffer_size); if (status != 0) + { + ERROR ("powerdns plugin: powerdns_get_data failed."); return (-1); + } keys_list = strdup (item->command); if (keys_list == NULL) @@ -768,7 +819,7 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */ */ if (strcasecmp ("Server", ci->key) == 0) { - item->server_type = SRV_AUTHORATIVE; + item->server_type = SRV_AUTHORITATIVE; item->func = powerdns_read_server; item->socktype = SOCK_STREAM; socket_temp = strdup (SERVER_SOCKET); @@ -817,15 +868,9 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */ break; } - if (item->command == NULL) - { - ERROR ("powerdns plugin: item->command == NULL."); - status = -1; - break; - } - item->sockaddr.sun_family = AF_UNIX; - sstrncpy (item->sockaddr.sun_path, socket_temp, UNIX_PATH_MAX); + sstrncpy (item->sockaddr.sun_path, socket_temp, + sizeof (item->sockaddr.sun_path)); e = llentry_create (item->instance, item); if (e == NULL) @@ -874,13 +919,20 @@ static int powerdns_config (oconfig_item_t *ci) /* {{{ */ if ((strcasecmp ("Server", option->key) == 0) || (strcasecmp ("Recursor", option->key) == 0)) powerdns_config_add_server (option); - if (strcasecmp ("LocalSocket", option->key) == 0) + else if (strcasecmp ("LocalSocket", option->key) == 0) { - char *temp = strdup (option->key); - if (temp == NULL) - return (1); - sfree (local_sockpath); - local_sockpath = temp; + if ((option->values_num != 1) || (option->values[0].type != OCONFIG_TYPE_STRING)) + { + WARNING ("powerdns plugin: `%s' needs exactly one string argument.", option->key); + } + else + { + char *temp = strdup (option->values[0].value.string); + if (temp == NULL) + return (1); + sfree (local_sockpath); + local_sockpath = temp; + } } else {