1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
/* Copyright (C) Knot Resolver contributors. Licensed under GNU GPLv3 or
* (at your option) any later version. See COPYING for text of the license.
*
* This module logs (query name, type) pairs which failed DNSSEC validation. */
#include <libknot/packet/pkt.h>
#include <libknot/dname.h>
#include <ccan/json/json.h>
#include <contrib/cleanup.h>
#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)
{
if (!(ctx->state & KR_STATE_FAIL)
|| !ctx->req
|| !ctx->req->current_query
|| !ctx->req->current_query->flags.DNSSEC_BOGUS
|| knot_wire_get_qdcount(pkt->wire) != 1)
return ctx->state;
auto_free char *qname_text = kr_dname_text(knot_pkt_qname(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: <counter>, name: <qname>, type: <qtype>}, ... ]
*/
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)
{
static kr_layer_api_t _layer = {
.consume = &consume,
};
_layer.data = module;
return &_layer;
}
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)
|