req->vars_ref = LUA_NOREF;
req->uid = uid;
req->qsource.flags.xdp = is_xdp;
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_NONE, NULL);
array_init(req->qsource.headers);
if (session) {
req->qsource.flags.tcp = session_get_handle(session)->type == UV_TCP;
#include <libknot/errcode.h>
#include <libknot/dname.h>
#include <libknot/rrset.h>
+#include <libknot/version.h>
/* Function attributes */
#if __GNUC__ >= 4
#define KR_DNAME_STR_MAXLEN (KNOT_DNAME_TXT_MAXLEN + 1)
#define KR_RRTYPE_STR_MAXLEN (16 + 1)
+/* Compatibility with libknot<3.1.0 */
+#if KNOT_VERSION_HEX < 0x030100
+#define KNOT_EDNS_EDE_NONE (-1)
+#endif
+
/*
* Address sanitizer hints.
*/
--- /dev/null
+#include <libknot/rrtype/opt.h>
+
+#include "lib/module.h"
+#include "daemon/engine.h"
+
+static int extended_error_finalize(kr_layer_t *ctx) {
+ struct kr_request *req = ctx->req;
+ const knot_rrset_t *src_opt = req->qsource.packet->opt_rr;
+ const struct kr_extended_error *ede = &req->extended_error;
+
+ if (ede->info_code == KNOT_EDNS_EDE_NONE /* no extended error */
+ || src_opt == NULL /* no EDNS in query */
+ || kr_fails_assert(ede->info_code >= 0 && ede->info_code < UINT16_MAX) /* info code out of range */
+ || kr_fails_assert(req->answer->opt_rr) /* sanity check - answer should have EDNS */
+ ) {
+ return ctx->state;
+ }
+
+ const uint16_t info_code = (uint16_t)ede->info_code;
+ const size_t extra_len = ede->extra_text ? strlen(ede->extra_text) : 0;
+ uint8_t buf[sizeof(info_code) + extra_len];
+ knot_wire_write_u16(buf, info_code);
+ if (extra_len)
+ memcpy(buf + sizeof(info_code), ede->extra_text, extra_len);
+
+ if (knot_edns_add_option(req->answer->opt_rr, KNOT_EDNS_OPTION_EDE,
+ sizeof(buf), buf, &req->pool) != KNOT_EOK) {
+ /* something went wrong and there is no way to salvage content of OPT RRset */
+ kr_log_req(req, 0, 0, EDE, "unable to add Extended Error option\n");
+ knot_rrset_clear(req->answer->opt_rr, &req->pool);
+ }
+
+ return ctx->state;
+}
+
+KR_EXPORT
+int extended_error_init(struct kr_module *module) {
+ static kr_layer_api_t layer = {
+ .answer_finalize = &extended_error_finalize,
+ };
+ layer.data = module;
+ module->layer = &layer;
+
+ return kr_ok();
+}
+
+KR_MODULE_EXPORT(extended_error)
--- /dev/null
+# C module: extended_error
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+extended_error_src = files([
+ 'extended_error.c',
+])
+c_src_lint += extended_error_src
+
+extended_error_mod = shared_module(
+ 'extended_error',
+ extended_error_src,
+ dependencies: [
+ libknot,
+ luajit_inc,
+ ],
+ include_directories: mod_inc_dir,
+ name_prefix: '',
+ install: true,
+ install_dir: modules_dir,
+)