X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fbind.c;h=497fcb657ad307272e6e87ba6d10c41a91cb480d;hb=aff80830f1154a5b6c4da16a0b1033aafde14e24;hp=8e785d98004f4be270a12b5a4979076468eb83a0;hpb=6597f3a6584704f92f824f3cf7bac3369102e8a0;p=collectd.git diff --git a/src/bind.c b/src/bind.c index 8e785d98..497fcb65 100644 --- a/src/bind.c +++ b/src/bind.c @@ -1,7 +1,7 @@ /** * collectd - src/bind.c - * Copyright (C) 2009 Bruno Prémont - * Copyright (C) 2009 Florian Forster + * Copyright (C) 2009 Bruno Prémont + * Copyright (C) 2009,2010 Florian Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,27 +18,13 @@ * * Authors: * Bruno Prémont - * Florian Forster + * Florian Forster **/ -/* Set to C99 and POSIX code */ -#ifndef _ISOC99_SOURCE -# define _ISOC99_SOURCE -#endif -#ifndef _POSIX_SOURCE -# define _POSIX_SOURCE -#endif -#ifndef _POSIX_C_SOURCE -# define _POSIX_C_SOURCE 200112L -#endif -#ifndef _REENTRANT -# define _REENTRANT -#endif +#include "config.h" + #ifndef _XOPEN_SOURCE -# define _XOPEN_SOURCE 600 -#endif -#ifndef _BSD_SOURCE -# define _BSD_SOURCE +# define _XOPEN_SOURCE 600 /* glibc2 needs this for strptime */ #endif #include "collectd.h" @@ -46,6 +32,12 @@ #include "plugin.h" #include "configfile.h" +/* Some versions of libcurl don't include this themselves and then don't have + * fd_set available. */ +#if HAVE_SYS_SELECT_H +# include +#endif + #include #include #include @@ -59,7 +51,7 @@ * `list_info_ptr_t' are passed to the callbacks in the `void *user_data' * pointer. */ -typedef int (*list_callback_t) (const char *name, counter_t value, +typedef int (*list_callback_t) (const char *name, value_t value, time_t current_time, void *user_data); struct cb_view_s @@ -131,7 +123,7 @@ static const translation_info_t nsstats_translation_table[] = /* {{{ */ /* Rejects */ { "AuthQryRej", "dns_reject", "authorative" }, { "RecQryRej", "dns_reject", "recursive" }, - { "XfrRej", "dns_reject", "transer" }, + { "XfrRej", "dns_reject", "transfer" }, { "UpdateRej", "dns_reject", "update" }, /* Responses */ { "Response", "dns_response", "normal" }, @@ -178,7 +170,7 @@ static const translation_info_t zonestats_translation_table[] = /* {{{ */ { "NotifyRej", "dns_notify", "rejected" }, /* SOA/AXFS/IXFS requests */ { "SOAOutv4", "dns_opcode", "SOA-IPv4" }, - { "SOAOutv6", "dns_opcode", "SOA-IPv4" }, + { "SOAOutv6", "dns_opcode", "SOA-IPv6" }, { "AXFRReqv4", "dns_opcode", "AXFR-IPv4" }, { "AXFRReqv6", "dns_opcode", "AXFR-IPv6" }, { "IXFRReqv4", "dns_opcode", "IXFR-IPv4" }, @@ -239,45 +231,32 @@ static int memsummary_translation_table_length = STATIC_ARRAY_SIZE (memsummary_translation_table); /* }}} */ -static void remove_special (char *buffer, size_t buffer_size) /* {{{ */ -{ - size_t i; - - for (i = 0; i < buffer_size; i++) - { - if (buffer[i] == 0) - return; - if ((!isalnum ((int) buffer[i])) && (buffer[i] != '-')) - buffer[i] = '_'; - } -} /* }}} void remove_special */ - -static void submit_counter(time_t ts, const char *plugin_instance, /* {{{ */ - const char *type, const char *type_instance, counter_t value) +static void submit (time_t ts, const char *plugin_instance, /* {{{ */ + const char *type, const char *type_instance, value_t value) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = value; + values[0] = value; vl.values = values; vl.values_len = 1; - vl.time = ts; + vl.time = TIME_T_TO_CDTIME_T (ts); sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "bind", sizeof(vl.plugin)); if (plugin_instance) { sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance)); - remove_special (vl.plugin_instance, sizeof (vl.plugin_instance)); + replace_special (vl.plugin_instance, sizeof (vl.plugin_instance)); } sstrncpy(vl.type, type, sizeof(vl.type)); if (type_instance) { sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - remove_special (vl.plugin_instance, sizeof (vl.plugin_instance)); + replace_special (vl.plugin_instance, sizeof (vl.plugin_instance)); } plugin_dispatch_values(&vl); -} /* }}} void submit_counter */ +} /* }}} void submit */ static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */ size_t nmemb, void __attribute__((unused)) *stream) @@ -312,7 +291,7 @@ static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */ * Callback, that's called with a translation table. * (Plugin instance is fixed, type and type instance come from lookup table.) */ -static int bind_xml_table_callback (const char *name, counter_t value, /* {{{ */ +static int bind_xml_table_callback (const char *name, value_t value, /* {{{ */ time_t current_time, void *user_data) { translation_table_ptr_t *table = (translation_table_ptr_t *) user_data; @@ -326,7 +305,7 @@ static int bind_xml_table_callback (const char *name, counter_t value, /* {{{ */ if (strcmp (table->table[i].xml_name, name) != 0) continue; - submit_counter (current_time, + submit (current_time, table->plugin_instance, table->table[i].type, table->table[i].type_instance, @@ -342,14 +321,14 @@ static int bind_xml_table_callback (const char *name, counter_t value, /* {{{ */ * (Plugin instance and type are fixed, xml name is used as type instance.) */ static int bind_xml_list_callback (const char *name, /* {{{ */ - counter_t value, time_t current_time, void *user_data) + value_t value, time_t current_time, void *user_data) { list_info_ptr_t *list_info = (list_info_ptr_t *) user_data; if (list_info == NULL) return (-1); - submit_counter (current_time, + submit (current_time, list_info->plugin_instance, list_info->type, /* type instance = */ name, @@ -358,36 +337,62 @@ static int bind_xml_list_callback (const char *name, /* {{{ */ return (0); } /* }}} int bind_xml_list_callback */ -static int bind_xml_read_counter (xmlDoc *doc, xmlNode *node, /* {{{ */ - counter_t *ret_value) +static int bind_xml_read_derive (xmlDoc *doc, xmlNode *node, /* {{{ */ + derive_t *ret_value) +{ + char *str_ptr; + value_t value; + int status; + + str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) + { + ERROR ("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed."); + return (-1); + } + + status = parse_value (str_ptr, &value, DS_TYPE_DERIVE); + if (status != 0) + { + ERROR ("bind plugin: Parsing string \"%s\" to derive value failed.", + str_ptr); + return (-1); + } + + *ret_value = value.derive; + return (0); +} /* }}} int bind_xml_read_derive */ + +static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */ + gauge_t *ret_value) { char *str_ptr, *end_ptr; - long long int value; + double value; str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); if (str_ptr == NULL) { - ERROR ("bind plugin: bind_xml_read_counter: xmlNodeListGetString failed."); + ERROR ("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed."); return (-1); } errno = 0; - value = strtoll (str_ptr, &end_ptr, 10); + value = strtod (str_ptr, &end_ptr); xmlFree(str_ptr); if (str_ptr == end_ptr || errno) { if (errno && (value < 0)) - ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with underflow."); + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with underflow."); else if (errno && (value > 0)) - ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with overflow."); + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with overflow."); else - ERROR ("bind plugin: bind_xml_read_counter: strtoll failed."); + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed."); return (-1); } - *ret_value = value; + *ret_value = (gauge_t) value; return (0); -} /* }}} int bind_xml_read_counter */ +} /* }}} int bind_xml_read_gauge */ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */ xmlDoc *doc, xmlXPathContext *xpathCtx, time_t *ret_value) @@ -447,7 +452,7 @@ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */ return (-1); } - *ret_value = timegm(&tm); + *ret_value = mktime(&tm); xmlXPathFreeObject (xpathObj); return (0); @@ -459,14 +464,14 @@ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */ * Reads statistics in the form: * * QUERY - * 123 + * 123 * */ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ */ list_callback_t list_callback, void *user_data, xmlDoc *doc, xmlXPathContext *xpathCtx, - time_t current_time) + time_t current_time, int ds_type) { xmlXPathObject *xpathObj = NULL; int num_entries; @@ -486,10 +491,15 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ * { xmlNode *name_node = NULL; xmlNode *counter = NULL; + xmlNode *parent; xmlNode *child; + parent = xpathObj->nodesetval->nodeTab[i]; + DEBUG ("bind plugin: bind_parse_generic_name_value: parent->name = %s;", + (char *) parent->name); + /* Iterate over all child nodes. */ - for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; + for (child = parent->xmlChildrenNode; child != NULL; child = child->next) { @@ -506,10 +516,13 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ * { char *name = (char *) xmlNodeListGetString (doc, name_node->xmlChildrenNode, 1); - counter_t value; + value_t value; int status; - status = bind_xml_read_counter (doc, counter, &value); + if (ds_type == DS_TYPE_GAUGE) + status = bind_xml_read_gauge (doc, counter, &value.gauge); + else + status = bind_xml_read_derive (doc, counter, &value.derive); if (status != 0) continue; @@ -545,7 +558,7 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ * list_callback_t list_callback, void *user_data, xmlDoc *doc, xmlXPathContext *xpathCtx, - time_t current_time) + time_t current_time, int ds_type) { xmlXPathObject *xpathObj = NULL; int num_entries; @@ -571,14 +584,18 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ * child = child->next) { char *node_name; - counter_t value; + value_t value; int status; if (child->type != XML_ELEMENT_NODE) continue; node_name = (char *) child->name; - status = bind_xml_read_counter (doc, child, &value); + + if (ds_type == DS_TYPE_GAUGE) + status = bind_xml_read_gauge (doc, child, &value.gauge); + else + status = bind_xml_read_derive (doc, child, &value.derive); if (status != 0) continue; @@ -663,7 +680,7 @@ static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_value_list (/* xpath = */ "counters", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, path_ctx, current_time); + doc, path_ctx, current_time, DS_TYPE_COUNTER); } /* }}} */ xmlXPathFreeObject (path_obj); @@ -769,7 +786,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ list_info_ptr_t list_info = { plugin_instance, - /* type = */ "dns_qtype" + /* type = */ "dns_qtype_gauge" }; ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-qtypes", @@ -778,7 +795,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_name_value (/* xpath = */ "rdtype", /* callback = */ bind_xml_list_callback, /* user_data = */ &list_info, - doc, path_ctx, current_time); + doc, path_ctx, current_time, DS_TYPE_COUNTER); } /* }}} */ if (view->resolver_stats != 0) /* {{{ */ @@ -797,7 +814,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_name_value ("resstat", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, path_ctx, current_time); + doc, path_ctx, current_time, DS_TYPE_COUNTER); } /* }}} */ if (view->cacherrsets != 0) /* {{{ */ @@ -806,7 +823,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ list_info_ptr_t list_info = { plugin_instance, - /* type = */ "dns_qtype" + /* type = */ "dns_qtype_gauge" }; ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-cache_rr_sets", @@ -815,7 +832,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_name_value (/* xpath = */ "cache/rrset", /* callback = */ bind_xml_list_callback, /* user_data = */ &list_info, - doc, path_ctx, current_time); + doc, path_ctx, current_time, DS_TYPE_GAUGE); } /* }}} */ if (view->zones_num > 0) @@ -904,7 +921,7 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_name_value (/* xpath = */ "server/requests/opcode", /* callback = */ bind_xml_list_callback, /* user_data = */ &list_info, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } /* XPath: server/queries-in/rdtype @@ -929,7 +946,7 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_name_value (/* xpath = */ "server/queries-in/rdtype", /* callback = */ bind_xml_list_callback, /* user_data = */ &list_info, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } /* XPath: server/nsstats, server/nsstat @@ -972,14 +989,14 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_value_list ("server/nsstats", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } else { bind_parse_generic_name_value ("server/nsstat", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } } @@ -1018,14 +1035,14 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_value_list ("server/zonestats", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } else { bind_parse_generic_name_value ("server/zonestat", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } } @@ -1065,14 +1082,14 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_value_list ("server/resstats", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } else { bind_parse_generic_name_value ("server/resstat", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_COUNTER); } } @@ -1099,7 +1116,7 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ bind_parse_generic_value_list ("memory/summary", /* callback = */ bind_xml_table_callback, /* user_data = */ &table_ptr, - doc, xpathCtx, current_time); + doc, xpathCtx, current_time, DS_TYPE_GAUGE); } if (views_num > 0) @@ -1315,7 +1332,16 @@ static int bind_config (oconfig_item_t *ci) /* {{{ */ { oconfig_item_t *child = ci->children + i; - if (strcasecmp ("OpCodes", child->key) == 0) + if (strcasecmp ("Url", child->key) == 0) { + if ((child->values_num != 1) || (child->values[0].type != OCONFIG_TYPE_STRING)) + { + WARNING ("bind plugin: The `Url' option needs " + "exactly one string argument."); + return (-1); + } + + url = strdup (child->values[0].value.string); + } else if (strcasecmp ("OpCodes", child->key) == 0) bind_config_set_bool ("OpCodes", &global_opcodes, child); else if (strcasecmp ("QTypes", child->key) == 0) bind_config_set_bool ("QTypes", &global_qtypes, child); @@ -1326,7 +1352,7 @@ static int bind_config (oconfig_item_t *ci) /* {{{ */ else if (strcasecmp ("ResolverStats", child->key) == 0) bind_config_set_bool ("ResolverStats", &global_resolver_stats, child); else if (strcasecmp ("MemoryStats", child->key) == 0) - bind_config_set_bool ("MemoryStats", &global_resolver_stats, child); + bind_config_set_bool ("MemoryStats", &global_memory_stats, child); else if (strcasecmp ("View", child->key) == 0) bind_config_add_view (child); else @@ -1355,6 +1381,7 @@ static int bind_init (void) /* {{{ */ curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION); curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error); curl_easy_setopt (curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL); + curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); return (0); } /* }}} int bind_init */