Commit d263f5b6 authored by Mark Karpilovskij's avatar Mark Karpilovskij Committed by Daniel Salzman

mod-stats: added counters for EDNS option codes

parent 4ae27458
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -15,6 +15,7 @@
*/
#include "contrib/macros.h"
#include "contrib/wire_ctx.h"
#include "knot/include/module.h"
#include "knot/nameserver/xfr.h" // Dependency on qdata->extra!
......@@ -25,6 +26,8 @@
#define MOD_EDNS "\x0D""edns-presence"
#define MOD_FLAG "\x0D""flag-presence"
#define MOD_RCODE "\x0D""response-code"
#define MOD_REQ_EOPT "\x13""request-edns-option"
#define MOD_RESP_EOPT "\x14""response-edns-option"
#define MOD_NODATA "\x0C""reply-nodata"
#define MOD_QTYPE "\x0A""query-type"
#define MOD_QSIZE "\x0A""query-size"
......@@ -40,6 +43,8 @@ const yp_item_t stats_conf[] = {
{ MOD_EDNS, YP_TBOOL, YP_VNONE },
{ MOD_FLAG, YP_TBOOL, YP_VNONE },
{ MOD_RCODE, YP_TBOOL, YP_VBOOL = { true } },
{ MOD_REQ_EOPT, YP_TBOOL, YP_VNONE },
{ MOD_RESP_EOPT, YP_TBOOL, YP_VNONE },
{ MOD_NODATA, YP_TBOOL, YP_VNONE },
{ MOD_QTYPE, YP_TBOOL, YP_VNONE },
{ MOD_QSIZE, YP_TBOOL, YP_VNONE },
......@@ -55,6 +60,8 @@ enum {
CTR_EDNS,
CTR_FLAG,
CTR_RCODE,
CTR_REQ_EOPT,
CTR_RESP_EOPT,
CTR_NODATA,
CTR_QTYPE,
CTR_QSIZE,
......@@ -69,6 +76,8 @@ typedef struct {
bool edns;
bool flag;
bool rcode;
bool req_eopt;
bool resp_eopt;
bool nodata;
bool qtype;
bool qsize;
......@@ -230,6 +239,24 @@ static char *rcode_to_str(uint32_t idx, uint32_t count)
}
}
#define EOPT_OTHER (KNOT_EDNS_MAX_OPTION_CODE + 1)
#define req_eopt_to_str eopt_to_str
#define resp_eopt_to_str eopt_to_str
static char *eopt_to_str(uint32_t idx, uint32_t count)
{
if (idx >= EOPT_OTHER) {
return strdup(OTHER);
}
char str[32];
if (knot_opt_code_to_string(idx, str, sizeof(str)) < 0) {
return NULL;
} else {
return strdup(str);
}
}
enum {
QTYPE_OTHER = 0,
QTYPE_MIN1 = 1,
......@@ -293,11 +320,13 @@ static char *size_to_str(uint32_t idx, uint32_t count)
}
}
static char *qsize_to_str(uint32_t idx, uint32_t count) {
static char *qsize_to_str(uint32_t idx, uint32_t count)
{
return size_to_str(idx, count);
}
static char *rsize_to_str(uint32_t idx, uint32_t count) {
static char *rsize_to_str(uint32_t idx, uint32_t count)
{
return size_to_str(idx, count);
}
......@@ -311,6 +340,8 @@ static const ctr_desc_t ctr_descs[] = {
item(EDNS, edns, EDNS__COUNT),
item(FLAG, flag, FLAG__COUNT),
item(RCODE, rcode, RCODE_OTHER + 1),
item(REQ_EOPT, req_eopt, EOPT_OTHER + 1),
item(RESP_EOPT, resp_eopt, EOPT_OTHER + 1),
item(NODATA, nodata, NODATA__COUNT),
item(QTYPE, qtype, QTYPE__COUNT),
item(QSIZE, qsize, QSIZE_MAX_IDX + 1),
......@@ -318,6 +349,21 @@ static const ctr_desc_t ctr_descs[] = {
{ NULL }
};
static void incr_edns_option(knotd_mod_t *mod, const knot_pkt_t *pkt, unsigned ctr_name)
{
knot_rdata_t *rdata = knot_rdataset_at(&pkt->opt_rr->rrs, 0);
wire_ctx_t wire = wire_ctx_init(knot_rdata_data(rdata), knot_rdata_rdlen(rdata));
while (wire_ctx_available(&wire) > 0) {
uint16_t opt_code = wire_ctx_read_u16(&wire);
uint16_t opt_len = wire_ctx_read_u16(&wire);
wire_ctx_skip(&wire, opt_len);
if (wire.error != KNOT_EOK) {
break;
}
knotd_mod_stats_incr(mod, ctr_name, MIN(opt_code, EOPT_OTHER), 1);
}
}
static knotd_state_t update_counters(knotd_state_t state, knot_pkt_t *pkt,
knotd_qdata_t *qdata, knotd_mod_t *mod)
{
......@@ -471,6 +517,14 @@ static knotd_state_t update_counters(knotd_state_t state, knot_pkt_t *pkt,
}
}
// Count EDNS options.
if (stats->req_eopt && !knot_rrset_empty(qdata->query->opt_rr)) {
incr_edns_option(mod, qdata->query, CTR_REQ_EOPT);
}
if (stats->resp_eopt && !knot_rrset_empty(pkt->opt_rr)) {
incr_edns_option(mod, pkt, CTR_RESP_EOPT);
}
// Return if not query operation.
if (operation != OPERATION_QUERY) {
return state;
......
......@@ -49,6 +49,8 @@ Module reference
edns-presence: BOOL
flag-presence: BOOL
response-code: BOOL
request-edns-option: BOOL
response-edns-option: BOOL
reply-nodata: BOOL
query-type: BOOL
query-size: BOOL
......@@ -169,6 +171,30 @@ If enabled, outgoing response code is counted:
*Default:* on
.. _mod-stats_request-edns-option:
request-edns-option
...................
If enabled, EDNS options in requests are counted by their code:
* CODE0
* ...
* EDNS-KEY-TAG (CODE14)
* other - All other codes
*Default:* off
.. _mod-stats_response-edns-option:
response-edns-option
....................
If enabled, EDNS options in responses are counted by their code. See
:ref:`mod-stats_request-edns-option`.
*Default:* off
.. _mod-stats_reply-nodata:
reply-nodata
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -369,3 +369,43 @@ bool knot_rrtype_should_be_lowercased(const uint16_t type)
type == KNOT_RRTYPE_DNAME ||
type == KNOT_RRTYPE_RRSIG;
}
_public_
int knot_opt_code_to_string(const uint16_t code, char *out, const size_t out_len)
{
if (out == NULL) {
return -1;
}
const char *name = NULL;
switch (code) {
case 1: name = "LLQ"; break;
case 2: name = "UL"; break;
case 3: name = "NSID"; break;
case 5: name = "DAU"; break;
case 6: name = "DHU"; break;
case 7: name = "N3U"; break;
case 8: name = "EDNS-CLIENT-SUBNET"; break;
case 9: name = "EDNS-EXPIRE"; break;
case 10: name = "COOKIE"; break;
case 11: name = "EDNS-TCP-KEEPALIVE"; break;
case 12: name = "PADDING"; break;
case 13: name = "CHAIN"; break;
case 14: name = "EDNS-KEY-TAG"; break;
}
int ret;
if (name != NULL) {
ret = snprintf(out, out_len, "%s", name);
} else {
ret = snprintf(out, out_len, "CODE%u", code);
}
if (ret <= 0 || (size_t)ret >= out_len) {
return -1;
} else {
return ret;
}
}
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -283,4 +283,16 @@ int knot_rrtype_additional_needed(const uint16_t type);
*/
bool knot_rrtype_should_be_lowercased(const uint16_t type);
/*!
* \brief Translates option code to string.
*
* \param code Code of the option to translate.
* \param out Buffer for the output string.
* \param out_len The available size of the buffer.
*
* \retval Length of output string.
* \retval -1 if error.
*/
int knot_opt_code_to_string(const uint16_t code, char *out, const size_t out_len);
/*! @} */
......@@ -67,6 +67,9 @@ enum knot_edns_const {
KNOT_EDNS_OPTION_PADDING = 12,
/*! \brief EDNS Chain query option code. */
KNOT_EDNS_OPTION_CHAIN = 13,
/*! \brief Maximal currently relevant option code. */
KNOT_EDNS_MAX_OPTION_CODE = 14,
};
/* Helpers for splitting extended RCODE. */
......
......@@ -267,6 +267,8 @@ class ModStats(KnotModule):
self._bool(conf, "edns-presence", True)
self._bool(conf, "flag-presence", True)
self._bool(conf, "response-code", True)
self._bool(conf, "request-edns-option", True)
self._bool(conf, "response-edns-option", True)
self._bool(conf, "reply-nodata", True)
self._bool(conf, "query-type", True)
self._bool(conf, "query-size", True)
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -25,7 +25,7 @@
int main(int argc, char *argv[])
{
plan(125);
plan_lazy();
const knot_rdata_descriptor_t *descr;
char name[BUF_LEN] = { 0 };
......@@ -350,5 +350,12 @@ int main(int argc, char *argv[])
ok(knot_rrtype_should_be_lowercased(KNOT_RRTYPE_RRSIG) != 0,
"rrtype is RRSIG");
ret = knot_opt_code_to_string(0, name, BUF_LEN);
ok(ret != -1 && strcmp(name, "CODE0") == 0, "opt to str, code 0");
ret = knot_opt_code_to_string(10, name, BUF_LEN);
ok(ret != -1 && strcmp(name, "COOKIE") == 0, "opt to str, code 10");
ret = knot_opt_code_to_string(65535, name, BUF_LEN);
ok(ret != -1 && strcmp(name, "CODE65535") == 0, "opt to str, code 65535");
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment