--- /dev/null
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
--- /dev/null
+$TTL 300
+. IN SOA dnshoster.root-servers.nil. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+tld. NS ns.tld.
+ns.tld. A 10.53.0.2
--- /dev/null
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db";
+};
--- /dev/null
+$TTL 300
+@ IN SOA hoster.tld. ns.tld. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+
+ NS ns
+ns A 10.52.0.2
+
+example NS ns1.other-tld.
+example NS ns2.other-tld.
+example NS ns3.other-tld.
+example NS ns4.other-tld.
+example NS ns5.other-tld.
+example NS ns6.other-tld.
+example NS ns7.other-tld.
+example NS ns8.other-tld.
+example NS ns9.other-tld.
+example NS ns10.other-tld.
+example NS ns11.other-tld.
+example NS ns12.other-tld.
+example NS ns13.other-tld.
+example NS ns14.other-tld.
+example NS ns15.other-tld.
+
+example NS ns.example
+
+ns.example A 10.53.0.20
+ns.example A 10.53.0.21
+ns.example A 10.53.0.22
+ns.example A 10.53.0.23
+ns.example A 10.53.0.24
+ns.example A 10.53.0.25
+ns.example A 10.53.0.26
+ns.example A 10.53.0.27
+ns.example A 10.53.0.28
+ns.example A 10.53.0.29
+ns.example A 10.53.0.30
+ns.example A 10.53.0.31
+ns.example A 10.53.0.32
+ns.example A 10.53.0.33
+ns.example A 10.53.0.34
+ns.example A 10.53.0.35
+ns.example A 10.53.0.36
+ns.example A 10.53.0.37
+ns.example A 10.53.0.38
+ns.example A 10.53.0.39
+ns.example A 10.53.0.40
+ns.example A 10.53.0.41
+ns.example A 10.53.0.42
+ns.example A 10.53.0.43
+
+ns.example AAAA 2001:db8::20
+ns.example AAAA 2001:db8::21
+ns.example AAAA 2001:db8::22
+ns.example AAAA 2001:db8::23
+ns.example AAAA 2001:db8::24
+ns.example AAAA 2001:db8::25
+ns.example AAAA 2001:db8::26
+ns.example AAAA 2001:db8::27
+ns.example AAAA 2001:db8::28
+ns.example AAAA 2001:db8::29
+ns.example AAAA 2001:db8::30
+ns.example AAAA 2001:db8::31
+ns.example AAAA 2001:db8::32
+ns.example AAAA 2001:db8::33
+ns.example AAAA 2001:db8::34
+ns.example AAAA 2001:db8::35
+ns.example AAAA 2001:db8::36
+ns.example AAAA 2001:db8::37
+ns.example AAAA 2001:db8::38
+ns.example AAAA 2001:db8::39
+ns.example AAAA 2001:db8::40
+ns.example AAAA 2001:db8::41
+ns.example AAAA 2001:db8::42
+ns.example AAAA 2001:db8::43
--- /dev/null
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ recursion yes;
+ dnssec-validation no;
+};
+
+server 10.53.0.2 {
+ // Avoid truncation of the additional section without TC, because some
+ // mandatory glues would already be in the additional section, thus the
+ // resolver wouldn't try again using TCP by itself.
+ tcp-only yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
--- /dev/null
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
--- /dev/null
+# 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.
+
+from re import compile as Re
+
+import isctest
+
+
+def test_cap_glues(ns3):
+ msg = isctest.query.create("example.tld.", "A")
+ isctest.query.udp(msg, ns3.ip)
+
+ with ns3.watch_log_from_here() as watcher:
+ ns3.rndc("dumpdb -deleg")
+ watcher.wait_for_line("dumpdb complete")
+ db = isctest.text.TextFile(f"{ns3.identifier}/named_dump.db")
+
+ names_len = len(db.grep(Re("example.tld. ... DELEG server-name=")))
+ if names_len == 12:
+ # 12 NS names, 1 NS with glues (so no server-name), so 13 NS in total.
+ allowed_suffixes = range(20, 40)
+ skipped_suffixes = range(40, 44)
+ assert len(db.grep(Re("example.tld. ... DELEG server-ipv4="))) == 1
+ assert (
+ len(db.grep(Re("example.tld. ... DELEG server-ipv4=.* server-ipv6="))) == 1
+ )
+
+ for n in allowed_suffixes:
+ assert len(db.grep(f"10.53.0.{n}")) == 1
+ assert len(db.grep(f"2001:db8::{n}")) == 1
+
+ for n in skipped_suffixes:
+ assert len(db.grep(f"10.53.0.{n}")) == 0
+ assert len(db.grep(f"2001:db8::{n}")) == 0
+ else:
+ # 13 NS names and no glues. This occurs if the 13 NS without glues
+ # has been processed first.
+ assert names_len == 13
+ assert len(db.grep(Re("example.tld. ... DELEG server-ipv4="))) == 0
+ assert len(db.grep(Re("example.tld. ... DELEG server-ipv6="))) == 0
#define DEFAULT_MAX_QUERIES 50
#endif /* ifndef DEFAULT_MAX_QUERIES */
+/*
+ * Cap on the number of glue addresses cached per NS owner in a referral
+ * delegation set. The resolver itself will only ever try a handful of
+ * addresses per NS, so accepting more from a referral is wasted memory.
+ */
+#define DELEG_MAX_GLUES_PER_NS 20
+
/* Hash table for zone counters */
#ifndef RES_DOMAIN_HASH_BITS
#define RES_DOMAIN_HASH_BITS 12
static void
cache_delegglue(dns_delegset_t *delegset, dns_deleg_t *deleg, dns_ttl_t *ttl,
dns_rdataset_t *rdataset) {
+ size_t naddrs = 0;
+
if (rdataset->ttl < *ttl) {
*ttl = rdataset->ttl;
}
dns_rdata_tostruct(&rdata, &a, NULL);
addr.type.in = a.in_addr;
dns_delegset_addaddr(delegset, deleg, &addr);
+ naddrs++;
+
+ if (naddrs >= DELEG_MAX_GLUES_PER_NS) {
+ break;
+ }
}
}
static void
cache_delegglue6(dns_delegset_t *delegset, dns_deleg_t *deleg, dns_ttl_t *ttl,
dns_rdataset_t *rdataset) {
+ size_t naddrs = 0;
+
if (rdataset->ttl < *ttl) {
*ttl = rdataset->ttl;
}
dns_rdata_tostruct(&rdata, &aaaa, NULL);
addr.type.in6 = aaaa.in6_addr;
dns_delegset_addaddr(delegset, deleg, &addr);
+ naddrs++;
+
+ if (naddrs >= DELEG_MAX_GLUES_PER_NS) {
+ break;
+ }
}
}
dns_name_getlabelsequence(rctx->ns_name, 1, labels - 1, parent);
}
+ size_t ns_count = 0;
+ size_t max_servers = fctx->res->view->max_delegation_servers;
+
DNS_RDATASET_FOREACH(rctx->ns_rdataset) {
dns_rdataset_t *gluerdataset = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_ns_t ns;
dns_deleg_t *deleg = NULL;
+ if (ns_count >= max_servers) {
+ break;
+ }
+ ns_count++;
+
/*
* We can't "group" all NS-based delegations into a single
* `dns_deleg_t` because some of them might have glues, some