ERROR("powerdns plugin: %s failed: %s", func, \
sstrerror(errno, errbuf, sizeof(errbuf))); \
} while (0)
+#define SOCK_ERROR(func, sockpath) \
+ do { \
+ char errbuf[1024]; \
+ ERROR("powerdns plugin: Socket `%s` %s failed: %s", sockpath, func, \
+ sstrerror(errno, errbuf, sizeof(errbuf))); \
+ } while (0)
#define SERVER_SOCKET LOCALSTATEDIR "/run/pdns.controlsocket"
#define SERVER_COMMAND "SHOW * \n"
{"ipv6-questions", "dns_question", "incoming-ipv6"},
{"malloc-bytes", "gauge", "malloc_bytes"},
{"max-mthread-stack", "gauge", "max_mthread_stack"},
- {"no-packet-error", "gauge", "no_packet_error"},
+ {"no-packet-error", "errors", "no_packet_error"},
{"noedns-outqueries", "dns_question", "outgoing-noedns"},
{"noping-outqueries", "dns_question", "outgoing-noping"},
{"over-capacity-drops", "dns_question", "incoming-over_capacity"},
/* <https://doc.powerdns.com/md/recursor/stats/> */
static void submit(const char *plugin_instance, /* {{{ */
- const char *pdns_type, const char *value) {
+ const char *pdns_type, const char *value_str) {
value_list_t vl = VALUE_LIST_INIT;
- value_t values[1];
+ value_t value;
const char *type = NULL;
const char *type_instance = NULL;
if (i >= lookup_table_length) {
INFO("powerdns plugin: submit: Not found in lookup table: %s = %s;",
- pdns_type, value);
+ pdns_type, value_str);
return;
}
return;
}
- if (0 != parse_value(value, &values[0], ds->ds[0].type)) {
+ if (0 != parse_value(value_str, &value, ds->ds[0].type)) {
ERROR("powerdns plugin: Cannot convert `%s' "
"to a number.",
- value);
+ value_str);
return;
}
- vl.values = values;
+ vl.values = &value;
vl.values_len = 1;
- 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)
plugin_dispatch_values(&vl);
} /* }}} static void submit */
-static int powerdns_get_data_dgram(list_item_t *item, /* {{{ */
- char **ret_buffer, size_t *ret_buffer_size) {
+static int powerdns_get_data_dgram(list_item_t *item, char **ret_buffer) {
+ /* {{{ */
int sd;
int status;
struct sockaddr_un sa_unix = {0};
- struct timeval stv_timeout;
cdtime_t cdt_timeout;
sd = socket(PF_UNIX, item->socktype, 0);
status = unlink(sa_unix.sun_path);
if ((status != 0) && (errno != ENOENT)) {
- FUNC_ERROR("unlink");
+ SOCK_ERROR("unlink", sa_unix.sun_path);
close(sd);
return (-1);
}
* and otherwise the daemon cannot answer. */
status = bind(sd, (struct sockaddr *)&sa_unix, sizeof(sa_unix));
if (status != 0) {
- FUNC_ERROR("bind");
+ SOCK_ERROR("bind", sa_unix.sun_path);
break;
}
/* Make the socket writeable by the daemon.. */
status = chmod(sa_unix.sun_path, 0666);
if (status != 0) {
- FUNC_ERROR("chmod");
+ SOCK_ERROR("chmod", sa_unix.sun_path);
break;
}
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));
+ status =
+ setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
+ &CDTIME_T_TO_TIMEVAL(cdt_timeout), sizeof(struct timeval));
if (status != 0) {
- FUNC_ERROR("setsockopt");
+ SOCK_ERROR("setsockopt", sa_unix.sun_path);
break;
}
status =
connect(sd, (struct sockaddr *)&item->sockaddr, sizeof(item->sockaddr));
if (status != 0) {
- FUNC_ERROR("connect");
+ SOCK_ERROR("connect", sa_unix.sun_path);
break;
}
status = send(sd, item->command, strlen(item->command), 0);
if (status < 0) {
- FUNC_ERROR("send");
+ SOCK_ERROR("send", sa_unix.sun_path);
break;
}
status = recv(sd, temp, sizeof(temp), /* flags = */ 0);
if (status < 0) {
- FUNC_ERROR("recv");
+ SOCK_ERROR("recv", sa_unix.sun_path);
break;
}
buffer_size = status + 1;
buffer[buffer_size - 1] = 0;
*ret_buffer = buffer;
- *ret_buffer_size = buffer_size;
-
return (0);
} /* }}} int powerdns_get_data_dgram */
-static int powerdns_get_data_stream(list_item_t *item, /* {{{ */
- char **ret_buffer,
- size_t *ret_buffer_size) {
+static int powerdns_get_data_stream(list_item_t *item, char **ret_buffer) {
+ /* {{{ */
int sd;
int status;
status =
connect(sd, (struct sockaddr *)&item->sockaddr, sizeof(item->sockaddr));
if (status != 0) {
- FUNC_ERROR("connect");
+ SOCK_ERROR("connect", item->sockaddr.sun_path);
close(sd);
return (-1);
}
status = send(sd, item->command, strlen(item->command) + 1,
/* flags = */ 0);
if (status < 0) {
- FUNC_ERROR("send");
+ SOCK_ERROR("send", item->sockaddr.sun_path);
close(sd);
return (-1);
}
status = recv(sd, temp, sizeof(temp), /* flags = */ 0);
if (status < 0) {
- FUNC_ERROR("recv");
+ SOCK_ERROR("recv", item->sockaddr.sun_path);
break;
- } else if (status == 0)
+ } else if (status == 0) {
break;
+ }
buffer_new = realloc(buffer, buffer_size + status + 1);
if (buffer_new == NULL) {
FUNC_ERROR("realloc");
- status = -1;
+ status = ENOMEM;
break;
}
buffer = buffer_new;
} /* while (42) */
close(sd);
- if (status < 0) {
+ if (status != 0) {
sfree(buffer);
- } else {
- assert(status == 0);
- *ret_buffer = buffer;
- *ret_buffer_size = buffer_size;
+ return status;
}
- return (status);
+ *ret_buffer = buffer;
+ return 0;
} /* }}} int powerdns_get_data_stream */
-static int powerdns_get_data(list_item_t *item, char **ret_buffer,
- size_t *ret_buffer_size) {
+static int powerdns_get_data(list_item_t *item, char **ret_buffer) {
if (item->socktype == SOCK_DGRAM)
- return (powerdns_get_data_dgram(item, ret_buffer, ret_buffer_size));
+ return (powerdns_get_data_dgram(item, ret_buffer));
else if (item->socktype == SOCK_STREAM)
- return (powerdns_get_data_stream(item, ret_buffer, ret_buffer_size));
+ return (powerdns_get_data_stream(item, ret_buffer));
else {
ERROR("powerdns plugin: Unknown socket type: %i", (int)item->socktype);
return (-1);
static int powerdns_read_server(list_item_t *item) /* {{{ */
{
- char *buffer = NULL;
- size_t buffer_size = 0;
- int status;
-
- char *dummy;
- char *saveptr;
-
- char *key;
- char *value;
-
- const char *const *fields;
- int fields_num;
-
if (item->command == NULL)
item->command = strdup(SERVER_COMMAND);
if (item->command == NULL) {
return (-1);
}
- status = powerdns_get_data(item, &buffer, &buffer_size);
- if (status != 0)
- return (-1);
+ char *buffer = NULL;
+ int status = powerdns_get_data(item, &buffer);
+ if (status != 0) {
+ ERROR("powerdns plugin: powerdns_get_data failed.");
+ return (status);
+ }
+ if (buffer == NULL) {
+ return EINVAL;
+ }
+ const char *const *fields = default_server_fields;
+ int fields_num = default_server_fields_num;
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);
/* 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;
+ char *dummy = buffer;
+ char *saveptr = NULL;
+ char *key;
while ((key = strtok_r(dummy, ",", &saveptr)) != NULL) {
dummy = NULL;
- value = strchr(key, '=');
+ char *value = strchr(key, '=');
if (value == NULL)
break;
static int powerdns_read_recursor(list_item_t *item) /* {{{ */
{
char *buffer = NULL;
- size_t buffer_size = 0;
int status;
char *dummy;
}
assert(item->command != NULL);
- status = powerdns_get_data(item, &buffer, &buffer_size);
+ status = powerdns_get_data(item, &buffer);
if (status != 0) {
ERROR("powerdns plugin: powerdns_get_data failed.");
return (-1);