From: Ulrich Wisser Date: Thu, 19 Jul 2018 02:19:18 +0000 (-0400) Subject: bogus_log: add list of most frequent bogus queries X-Git-Tag: v3.2.0~11^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1817d4b4a55a7847305411ac8bfd03c8d2c1234a;p=thirdparty%2Fknot-resolver.git bogus_log: add list of most frequent bogus queries --- diff --git a/modules/bogus_log/bogus_log.c b/modules/bogus_log/bogus_log.c index 25e214d13..679d857a8 100644 --- a/modules/bogus_log/bogus_log.c +++ b/modules/bogus_log/bogus_log.c @@ -4,10 +4,32 @@ * This module logs (query name, type) pairs which failed DNSSEC validation. */ #include +#include +#include #include #include "daemon/engine.h" #include "lib/layer.h" +#include "lib/generic/lru.h" + +/** @internal Compatibility wrapper for Lua < 5.2 */ +#if LUA_VERSION_NUM < 502 +#define lua_rawlen(L, obj) lua_objlen((L), (obj)) +#endif + +#ifdef LRU_REP_SIZE + #define FREQUENT_COUNT LRU_REP_SIZE /* Size of frequent tables */ +#else + #define FREQUENT_COUNT 5000 /* Size of frequent tables */ +#endif + +/** @internal LRU hash of most frequent names. */ +typedef lru_t(unsigned) namehash_t; + +/** @internal Stats data structure. */ +struct stat_data { + namehash_t *frequent; +}; static int consume(kr_layer_t *ctx, knot_pkt_t *pkt) { @@ -22,9 +44,89 @@ static int consume(kr_layer_t *ctx, knot_pkt_t *pkt) auto_free char *qtype_text = kr_rrtype_text(knot_pkt_qtype(pkt)); kr_log_error("DNSSEC validation failure %s %s\n", qname_text, qtype_text); + + /* log of most frequent bogus queries */ + uint16_t type = knot_pkt_qtype(pkt); + char key[sizeof(type) + KNOT_DNAME_MAXLEN]; + memcpy(key, &type, sizeof(type)); + int key_len = knot_dname_to_wire((uint8_t *)key + sizeof(type), knot_pkt_qname(pkt), KNOT_DNAME_MAXLEN); + if (key_len >= 0) { + struct kr_module *module = ctx->api->data; + struct stat_data *data = module->data; + unsigned *count = lru_get_new(data->frequent, key, key_len+sizeof(type), NULL); + if (count) + *count += 1; + } + return ctx->state; } +/** @internal Helper for dump_list: add a single namehash_t item to JSON. */ +static enum lru_apply_do dump_value(const char *key, uint len, unsigned *val, void *baton) +{ + uint16_t key_type = 0; + /* Extract query name, type and counter */ + memcpy(&key_type, key, sizeof(key_type)); + KR_DNAME_GET_STR(key_name, (uint8_t *)key + sizeof(key_type)); + KR_RRTYPE_GET_STR(type_str, key_type); + + /* Convert to JSON object */ + JsonNode *json_val = json_mkobject(); + json_append_member(json_val, "count", json_mknumber(*val)); + json_append_member(json_val, "name", json_mkstring(key_name)); + json_append_member(json_val, "type", json_mkstring(type_str)); + json_append_element((JsonNode *)baton, json_val); + return LRU_APPLY_DO_NOTHING; // keep the item +} + +/** + * List frequent names. + * + * Output: [{ count: , name: , type: }, ... ] + */ +static char* dump_list(void *env, struct kr_module *module, const char *args, namehash_t *table) +{ + if (!table) { + return NULL; + } + JsonNode *root = json_mkarray(); + lru_apply(table, dump_value, root); + char *ret = json_encode(root); + json_delete(root); + return ret; +} + +static char* dump_frequent(void *env, struct kr_module *module, const char *args) +{ + struct stat_data *data = module->data; + return dump_list(env, module, args, data->frequent); +} + +KR_EXPORT +int bogus_log_init(struct kr_module *module) +{ + struct stat_data *data = malloc(sizeof(*data)); + if (!data) { + return kr_error(ENOMEM); + } + memset(data, 0, sizeof(*data)); + module->data = data; + lru_create(&data->frequent, FREQUENT_COUNT, NULL, NULL); + return kr_ok(); +} + +KR_EXPORT +int bogus_log_deinit(struct kr_module *module) +{ + struct stat_data *data = module->data; + if (data) { + lru_free(data->frequent); + free(data); + } + return kr_ok(); +} + + KR_EXPORT const kr_layer_api_t *bogus_log_layer(struct kr_module *module) { @@ -35,4 +137,14 @@ const kr_layer_api_t *bogus_log_layer(struct kr_module *module) return &_layer; } -KR_MODULE_EXPORT(bogus_log) +KR_EXPORT +struct kr_prop *bogus_log_props(void) +{ + static struct kr_prop prop_list[] = { + { &dump_frequent, "frequent", "List most frequent queries.", }, + { NULL, NULL, NULL } + }; + return prop_list; +} + +KR_MODULE_EXPORT(bogus_log);