blob: 30d5df32ca0d25745d7573aab3d05c7264a9629c (
plain)
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
|
/* Copyright (C) CZ.NIC, z.s.p.o. <knot-resolver@labs.nic.cz>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* @file edns_keepalive.c
* @brief Minimalistic EDNS keepalive implementation on server side.
* If keepalive option is present in query,
* always reply with constant timeout value.
*
*/
#include <libknot/packet/pkt.h>
#include "daemon/worker.h"
#include "lib/module.h"
#include "lib/layer.h"
static int edns_keepalive_finalize(kr_layer_t *ctx)
{
struct kr_request *req = ctx->req;
knot_pkt_t *answer = req->answer;
const knot_rrset_t *src_opt = req->qsource.packet->opt_rr;
knot_rrset_t *answ_opt = answer->opt_rr;
const bool ka_want =
req->qsource.flags.tcp &&
src_opt != NULL &&
knot_edns_get_option(src_opt, KNOT_EDNS_OPTION_TCP_KEEPALIVE, NULL) &&
answ_opt != NULL;
if (!ka_want) {
return ctx->state;
}
const struct network *net = &the_worker->engine->net;
uint64_t timeout = net->tcp.in_idle_timeout / 100;
if (timeout > UINT16_MAX) {
timeout = UINT16_MAX;
}
knot_mm_t *pool = &answer->mm;
uint16_t ka_size = knot_edns_keepalive_size(timeout);
uint8_t ka_buf[ka_size];
int ret = knot_edns_keepalive_write(ka_buf, ka_size, timeout);
if (ret == KNOT_EOK) {
ret = knot_edns_add_option(answ_opt, KNOT_EDNS_OPTION_TCP_KEEPALIVE,
ka_size, ka_buf, pool);
}
if (ret != KNOT_EOK) {
ctx->state = KR_STATE_FAIL;
}
return ctx->state;
}
KR_EXPORT int edns_keepalive_init(struct kr_module *self)
{
static const kr_layer_api_t layer = {
.answer_finalize = &edns_keepalive_finalize,
};
self->layer = &layer;
return kr_ok();
}
KR_MODULE_EXPORT(edns_keepalive)
|