add support for dynamic PTR record

This commit is contained in:
Colin Vidal
2025-01-21 14:05:22 +01:00
parent d3db9ccf53
commit f71c032c8a
9 changed files with 346 additions and 0 deletions

View File

@@ -8,8 +8,11 @@ AM_CPPFLAGS += \
pkglib_LTLIBRARIES = filter-aaaa.la
pkglib_LTLIBRARIES += filter-a.la
pkglib_LTLIBRARIES += dynptrr.la
filter_aaaa_la_SOURCES = filter-aaaa.c
filter_a_la_SOURCES = filter-a.c
filter_aaaa_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
filter_a_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
dynptrr_la_SOURCES = dynptrr.c
dynptrr_la_LDFLAGS = -avoid-version -module -shared -export-dynamic

167
bin/plugins/dynptrr.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <ns/hooks.h>
#include <dns/view.h>
#include <dns/rdatalist.h>
#include <dns/byaddr.h>
typedef struct dynptrr dynptrr_t;
struct dynptrr {
isc_mem_t *mctx;
};
static ns_hookresult_t
dynptrr_nxdomain_begin(void *arg, void *cbdata, isc_result_t *resp) {
query_ctx_t *qctx = (query_ctx_t *)arg;
isc_mem_t *mctx = qctx->client->view->mctx;
dynptrr_t *inst = (dynptrr_t *)cbdata;
UNUSED(inst);
*resp = ISC_R_UNSET;
if (qctx->type != dns_rdatatype_ptr) {
return NS_HOOK_CONTINUE;
}
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
ISC_LOG_DEBUG(1), "dynptrr nxdomain begin");
dns_message_t *message = qctx->client->message;
dns_name_t *name = isc_mem_get(mctx, sizeof(*name));
dns_rdataset_t *synth = NULL;
dns_rdatalist_t *synthlist = NULL;
dns_rdata_t *synthdata = NULL;
dns_name_init(name);
dns_name_dup(qctx->client->query.qname, mctx, name);
char n[512];
dns_name_format(name, n, 512);
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
ISC_LOG_DEBUG(1), "dynptrr %s", n);
dns_message_gettemprdataset(message, &synth);
dns_rdataset_init(synth);
synth->ttl = 60;
synth->rdclass = dns_rdataclass_in;
synth->type = dns_rdatatype_ptr;
dns_message_gettemprdatalist(message, &synthlist);
dns_rdatalist_init(synthlist);
synthlist->ttl = 60;
synthlist->rdclass = dns_rdataclass_in;
synthlist->type = dns_rdatatype_ptr;
dns_message_gettemprdata(message, &synthdata);
dns_rdata_init(synthdata);
synthdata->rdclass = dns_rdataclass_in;
synthdata->type = dns_rdatatype_ptr;
/*
* It seems that for a ptr type, the data must be the ndata pointer of a
* dns_name_t. (I attempted putting a raw string instead, and it was a
* crash)
*/
synthdata->data = name->ndata;
synthdata->length = name->length;
ISC_LIST_APPEND(synthlist->rdata, synthdata, link);
dns_rdatalist_tordataset(synthlist, synth);
dns_rdataset_setownercase(synth, name);
dns_message_addname(message, name, DNS_SECTION_ANSWER);
ISC_LIST_APPEND(name->list, synth, link);
isc_result_t result = ns_query_done(qctx);
*resp = result;
/* ------------------------------------------------- */
// isc_netaddr_t peeraddr;
// isc_netaddr_fromsockaddr(&peeraddr, &qctx->client->peeraddr);
//
// char createdptrnamed[512];
// isc_buffer_t createdptrnameb;
// isc_buffer_init(&createdptrnameb, createdptrnamed, 512);
//
// dns_name_t *createdptrname = isc_mem_get(mctx, sizeof(*createdptrname));
// dns_name_init(createdptrname);
// dns_name_setbuffer(createdptrname, &createdptrnameb);
// isc_result_t r = dns_byaddr_createptrname(&peeraddr, createdptrname);
// isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
// ISC_LOG_DEBUG(1), "dynptrr %s", isc_result_totext(r));
// dns_name_format(createdptrname, n, 512);
// isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
// ISC_LOG_DEBUG(1), "dynptrr ptr %s", n);
// isc_mem_put(mctx, createdptrname, sizeof(*createdptrname));
//
/* ------------------------------------------------- */
return NS_HOOK_RETURN;
}
void
plugin_destroy(void **instp) {
REQUIRE(instp && *instp);
dynptrr_t *inst = *instp;
isc_mem_t *mctx = inst->mctx;
isc_mem_put(mctx, inst, sizeof(*inst));
*instp = NULL;
printf("dynptrr plugin_destroy\n");
}
int
plugin_version(void) {
printf("dynptrr plugin_version\n");
return NS_PLUGIN_VERSION;
}
isc_result_t
plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
unsigned long cfg_line, isc_mem_t *mctx, void *actx,
ns_hooktable_t *hooktable, void **instp) {
REQUIRE(cfg);
REQUIRE(mctx);
REQUIRE(actx);
REQUIRE(hooktable);
REQUIRE(instp && *instp == NULL);
printf("dynptrr plugin_register %s %s %ld\n", parameters, cfg_file,
cfg_line);
dynptrr_t *inst = isc_mem_get(mctx, sizeof(*inst));
*inst = (dynptrr_t){ .mctx = mctx };
*instp = inst;
const ns_hook_t testhook = {
.action = dynptrr_nxdomain_begin,
.action_data = inst
};
ns_hook_add(hooktable, mctx, NS_QUERY_NXDOMAIN_BEGIN, &testhook);
return ISC_R_SUCCESS;
}
isc_result_t
plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
unsigned long cfg_line, isc_mem_t *mctx, void *actx) {
REQUIRE(cfg);
REQUIRE(mctx);
REQUIRE(actx);
printf("dynptrr plugin_check %s %s %ld\n", parameters, cfg_file,
cfg_line);
return ISC_R_SUCCESS;
}

3
bin/tests/system/dynptrr/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
named.conf
named.memstats
named.run

View File

@@ -0,0 +1,25 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 120
@ SOA ns.example. hostmaster.ns.example. ( 1 3600 1200 604800 60 )
@ NS ns
@ MX 10 mx
ns A 10.53.0.1
AAAA fd92:7065:b8e:ffff::1
a-only NS 1.0.0.4
aaaa-only AAAA 2001:db8::5
dual A 1.0.0.6
dual AAAA 2001:db8::6
mx A 1.0.0.3
mx AAAA 2001:db8::3

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
options {
query-source address 10.53.0.1;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { fd92:7065:b8e:ffff::1; };
recursion no;
};
plugin query "../../../../plugins/.libs/dynptrr.so" {
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." { type primary; file "root.db"; };
zone "example" { type primary; file "example.db"; };

View File

@@ -0,0 +1,23 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 120
@ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 )
@ NS ns.utld
ns.utld A 10.53.0.1
ns.utld AAAA fd92:7065:b8e:ffff::1
;
example NS ns.example
ns.example A 10.53.0.1
ns.example AAAA fd92:7065:b8e:ffff::1
10.53.0.1 PTR ns.example

View File

@@ -0,0 +1,16 @@
#!/bin/sh
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. ../conf.sh
copy_setports ns1/named.conf.in ns1/named.conf

View File

@@ -0,0 +1,49 @@
#!/bin/sh
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
set -e
. ../conf.sh
status=0
n=0
rm -f dig.out.*
dig_with_opts() {
"${DIG}" -p "${PORT}" "${@}"
}
n=$((n + 1))
echo_i "PTR exists, dynptrr hook is not run ($n)"
ret=0
dig_with_opts ptr 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1
grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1
grep "ns.example" dig.out.ns1.test$n >/dev/null || ret=1
grep "dynptrr nxdomain begin" ns1/named.run && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "PTR does not exists, dynptrr hook is run ($n)"
ret=0
dig_with_opts ptr 10.53.0.2 @10.53.0.1 >dig.out.ns1.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns1.test${n} >/dev/null || ret=1
grep "dynptrr nxdomain begin" ns1/named.run || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
exit 1
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View File

@@ -0,0 +1,23 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import pytest
pytestmark = pytest.mark.extra_artifacts(
[
"managed-keys.bind.jnl",
"dig.out.*",
]
)
def test_dynptrr(run_tests_sh):
run_tests_sh()