X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fbind.c;h=28c1e56a74c880bb170d9d6efbfc7b2b0542ea80;hb=d2215ad1ade0993380566de703037bd533ac8f7a;hp=8e785d98004f4be270a12b5a4979076468eb83a0;hpb=6597f3a6584704f92f824f3cf7bac3369102e8a0;p=collectd.git diff --git a/src/bind.c b/src/bind.c index 8e785d98..28c1e56a 100644 --- a/src/bind.c +++ b/src/bind.c @@ -21,24 +21,10 @@ * 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,26 +231,13 @@ 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; @@ -268,16 +247,16 @@ static void submit_counter(time_t ts, const char *plugin_instance, /* {{{ */ 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, @@ -389,6 +368,37 @@ static int bind_xml_read_counter (xmlDoc *doc, xmlNode *node, /* {{{ */ return (0); } /* }}} int bind_xml_read_counter */ +static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */ + gauge_t *ret_value) +{ + char *str_ptr, *end_ptr; + double value; + + str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) + { + ERROR ("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed."); + return (-1); + } + + errno = 0; + 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_gauge: strtod failed with underflow."); + else if (errno && (value > 0)) + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with overflow."); + else + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed."); + return (-1); + } + + *ret_value = (gauge_t) value; + return (0); +} /* }}} 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 +457,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 +469,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 +496,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 +521,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_counter (doc, counter, &value.counter); if (status != 0) continue; @@ -545,7 +563,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 +589,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_counter (doc, child, &value.counter); if (status != 0) continue; @@ -663,7 +685,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); @@ -778,7 +800,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,16 +819,17 @@ 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); } /* }}} */ + /* Record types in the cache */ if (view->cacherrsets != 0) /* {{{ */ { char plugin_instance[DATA_MAX_NAME_LEN]; list_info_ptr_t list_info = { plugin_instance, - /* type = */ "dns_qtype" + /* type = */ "dns_qtype_cached" }; ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-cache_rr_sets", @@ -815,7 +838,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 +927,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 +952,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 +995,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 +1041,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 +1088,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 +1122,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 +1338,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 +1358,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 @@ -1351,10 +1383,12 @@ static int bind_init (void) /* {{{ */ return (-1); } + curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback); 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 */