mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 04:10:00 -04:00
fix: usr: fetch loop detection improvements
Fixes a case where an in-domain NS with an expired glue would fail to resolve.
Let's consider the following parent-side delegation (both for `foo.example.` and `dnshost.example.`
```
foo.example. 3600 NS ns.dnshost.example.
dnshost.example. 3600 NS ns.dnshost.example.
ns.dnshost.example. 3600 A 1.2.3.4
```
Then the child-side of `dnshost.example.`:
```
dnshost.example. 300 NS ns.dnshost.example.
ns.dnshost.example. 300 A 1.2.3.4
```
And then the child-side of `foo.example.`:
```
foo.example 3600 NS ns.dnshost.example.
a.foo.example 300 A 5.6.7.8
```
While there is a zone misconfiguration (the TTL of the delegation and glue doesn't match in the parent and the child), it is possible to resolve `a.foo.example` on a cold-cache resolver. However, after the `ns.dnshost.example.` glue expires, the resolution would have failed with a "fetch loop detected" error. This is now fixed.
Closes #5588
Merge branch '5588-loopfetches' into 'main'
See merge request isc-projects/bind9!11535
This commit is contained in:
commit
bc0e9f1ccb
15 changed files with 410 additions and 24 deletions
|
|
@ -120,6 +120,9 @@ extern unsigned int dns_zone_mkey_hour;
|
|||
extern unsigned int dns_zone_mkey_day;
|
||||
extern unsigned int dns_zone_mkey_month;
|
||||
|
||||
extern unsigned int dns_adb_entrywindow;
|
||||
extern unsigned int dns_adb_cachemin;
|
||||
|
||||
static bool want_stats = false;
|
||||
static char absolute_conffile[PATH_MAX];
|
||||
static char saved_command_line[4096] = { 0 };
|
||||
|
|
@ -723,6 +726,10 @@ parse_T_opt(char *option) {
|
|||
transferstuck = true;
|
||||
} else if (!strncmp(option, "tat=", 4)) {
|
||||
named_g_tat_interval = atoi(option + 4);
|
||||
} else if (!strncmp(option, "adbentrywindow=", 15)) {
|
||||
dns_adb_entrywindow = atoi(option + 15);
|
||||
} else if (!strncmp(option, "adbcachemin=", 12)) {
|
||||
dns_adb_cachemin = atoi(option + 12);
|
||||
} else {
|
||||
fprintf(stderr, "unknown -T flag '%s'\n", option);
|
||||
}
|
||||
|
|
|
|||
39
bin/tests/system/expiredglue/ns1/named.conf.j2
Normal file
39
bin/tests/system/expiredglue/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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;
|
||||
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;
|
||||
};
|
||||
|
||||
view "default" {
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db";
|
||||
};
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
24
bin/tests/system/expiredglue/ns1/root.db
Normal file
24
bin/tests/system/expiredglue/ns1/root.db
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; 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 300
|
||||
. IN SOA marka.isc.org. 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
|
||||
37
bin/tests/system/expiredglue/ns2/named.conf.j2
Normal file
37
bin/tests/system/expiredglue/ns2/named.conf.j2
Normal 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.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";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
28
bin/tests/system/expiredglue/ns2/tld.db
Normal file
28
bin/tests/system/expiredglue/ns2/tld.db
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; 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 300
|
||||
tld. IN SOA marka.isc.org. ns.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
tld. NS ns.tld.
|
||||
ns.tld. A 10.53.0.2
|
||||
|
||||
example.tld. NS ns.dnshoster.tld.
|
||||
missing.tld. NS ns.missing.tld.
|
||||
dnshoster.tld. NS ns.dnshoster.tld.
|
||||
|
||||
; Delegation's glue has a TTL of 300 on parent-side
|
||||
ns.dnshoster.tld. A 10.53.0.3
|
||||
24
bin/tests/system/expiredglue/ns3/dnshoster.tld.db
Normal file
24
bin/tests/system/expiredglue/ns3/dnshoster.tld.db
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; 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 300
|
||||
dnshoster.tld. IN SOA marka.isc.org. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
; The TTL of the delegation's glue child-side is 2 seconds.
|
||||
dnshoster.tld. NS ns.dnshoster.tld.
|
||||
ns.dnshoster.tld. 2 A 10.53.0.3
|
||||
a.dnshoster.tld. 2 A 10.53.0.10
|
||||
22
bin/tests/system/expiredglue/ns3/example.tld.db
Normal file
22
bin/tests/system/expiredglue/ns3/example.tld.db
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
; 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 300
|
||||
example.tld. IN SOA marka.isc.org. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
example.tld. NS ns.dnshoster.tld.
|
||||
a.example.tld. 2 A 10.53.0.10
|
||||
42
bin/tests/system/expiredglue/ns3/named.conf.j2
Normal file
42
bin/tests/system/expiredglue/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.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 no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "dnshoster.tld." {
|
||||
type primary;
|
||||
file "dnshoster.tld.db";
|
||||
};
|
||||
|
||||
zone "example.tld." {
|
||||
type primary;
|
||||
file "example.tld.db";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
1
bin/tests/system/expiredglue/ns4/named.args
Normal file
1
bin/tests/system/expiredglue/ns4/named.args
Normal file
|
|
@ -0,0 +1 @@
|
|||
-D expiredglue-ns4 -m record -c named.conf -d 99 -g -4 -T adbentrywindow=0 -T adbcachemin=1 -T maxcachesize=2097152
|
||||
37
bin/tests/system/expiredglue/ns4/named.conf.j2
Normal file
37
bin/tests/system/expiredglue/ns4/named.conf.j2
Normal 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.4;
|
||||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "root.hint";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
14
bin/tests/system/expiredglue/ns4/root.hint
Normal file
14
bin/tests/system/expiredglue/ns4/root.hint
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
; 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 999999
|
||||
. IN NS a.root-servers.nil.
|
||||
a.root-servers.nil. IN A 10.53.0.1
|
||||
55
bin/tests/system/expiredglue/tests_expiredglue.py
Normal file
55
bin/tests/system/expiredglue/tests_expiredglue.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# 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 time
|
||||
|
||||
import isctest
|
||||
|
||||
|
||||
def test_expiredglue(ns4):
|
||||
msg1 = isctest.query.create("a.example.tld.", "A")
|
||||
res1 = isctest.query.udp(msg1, ns4.ip)
|
||||
isctest.check.noerror(res1)
|
||||
isctest.check.rr_count_eq(res1.answer, 1)
|
||||
|
||||
msg2 = isctest.query.create("a.dnshoster.tld.", "A")
|
||||
res2 = isctest.query.udp(msg2, ns4.ip)
|
||||
isctest.check.rr_count_eq(res2.answer, 1)
|
||||
|
||||
msg3 = isctest.query.create("ns.dnshoster.tld.", "A")
|
||||
res3 = isctest.query.udp(msg3, ns4.ip)
|
||||
isctest.check.rr_count_eq(res3.answer, 1)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# Even if the glue is expired but the delegation is not, named
|
||||
# is able to "recover" by looking up the hints again and does
|
||||
# not bails out with a fetch loop detection.
|
||||
res1_2 = isctest.query.udp(msg1, ns4.ip)
|
||||
isctest.check.same_data(res1_2, res1)
|
||||
|
||||
time.sleep(3)
|
||||
res2_2 = isctest.query.udp(msg2, ns4.ip)
|
||||
isctest.check.same_data(res2_2, res2)
|
||||
|
||||
time.sleep(3)
|
||||
res3_2 = isctest.query.udp(msg3, ns4.ip)
|
||||
isctest.check.same_data(res3_2, res3)
|
||||
|
||||
|
||||
def test_loopdetected(ns4):
|
||||
msg = isctest.query.create("a.missing.tld.", "A")
|
||||
with ns4.watch_log_from_here() as watcher:
|
||||
res = isctest.query.udp(msg, ns4.ip)
|
||||
|
||||
# However, this is a valid fetch loop, and named detects it.
|
||||
watcher.wait_for_line("loop detected resolving 'ns.missing.tld/A'")
|
||||
isctest.check.servfail(res)
|
||||
|
|
@ -63,12 +63,8 @@
|
|||
/*!
|
||||
* For type 3 negative cache entries, we will remember that the address is
|
||||
* broken for this long. XXXMLG This is also used for actual addresses, too.
|
||||
* The intent is to keep us from constantly asking about A/AAAA records
|
||||
* if the zone has extremely low TTLs.
|
||||
*/
|
||||
#define ADB_CACHE_MINIMUM 10 /*%< seconds */
|
||||
#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
|
||||
#define ADB_ENTRY_WINDOW 60 /*%< seconds */
|
||||
|
||||
#define ADB_HASH_SIZE (1 << 12)
|
||||
|
||||
|
|
@ -284,6 +280,12 @@ ISC_REFCOUNT_TRACE_DECL(dns_adbentry);
|
|||
ISC_REFCOUNT_DECL(dns_adbentry);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ADB settings that can be tweaked with named -T option
|
||||
*/
|
||||
unsigned int dns_adb_entrywindow = 60;
|
||||
unsigned int dns_adb_cachemin = 10;
|
||||
|
||||
/*
|
||||
* Internal functions (and prototypes).
|
||||
*/
|
||||
|
|
@ -457,10 +459,10 @@ enum {
|
|||
* Due to the ttlclamp(), the TTL is never 0 unless the trust is ultimate,
|
||||
* in which case we need to set the expiration to have immediate effect.
|
||||
*/
|
||||
#define ADJUSTED_EXPIRE(expire, now, ttl) \
|
||||
((ttl != 0) \
|
||||
? ISC_MIN(expire, ISC_MAX(now + ADB_ENTRY_WINDOW, now + ttl)) \
|
||||
: INT_MAX)
|
||||
#define ADJUSTED_EXPIRE(expire, now, ttl) \
|
||||
((ttl != 0) ? ISC_MIN(expire, \
|
||||
ISC_MAX(now + dns_adb_entrywindow, now + ttl)) \
|
||||
: INT_MAX)
|
||||
|
||||
/*
|
||||
* Error states.
|
||||
|
|
@ -533,8 +535,12 @@ inc_adbstats(dns_adb_t *adb, isc_statscounter_t counter) {
|
|||
|
||||
static dns_ttl_t
|
||||
ttlclamp(dns_ttl_t ttl) {
|
||||
if (ttl < ADB_CACHE_MINIMUM) {
|
||||
ttl = ADB_CACHE_MINIMUM;
|
||||
if (ttl < dns_adb_cachemin) {
|
||||
/*
|
||||
* Avoid to constantly ask about A/AAAA records if the zone has
|
||||
* extremely low TTLs.
|
||||
*/
|
||||
ttl = dns_adb_cachemin;
|
||||
}
|
||||
if (ttl > ADB_CACHE_MAXIMUM) {
|
||||
ttl = ADB_CACHE_MAXIMUM;
|
||||
|
|
@ -567,7 +573,11 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|||
case dns_trust_additional:
|
||||
case dns_trust_pending_answer:
|
||||
case dns_trust_pending_additional:
|
||||
rdataset->ttl = ADB_CACHE_MINIMUM;
|
||||
/*
|
||||
* Avoid to constantly ask about A/AAAA records if the zone has
|
||||
* extremely low TTLs.
|
||||
*/
|
||||
rdataset->ttl = dns_adb_cachemin;
|
||||
break;
|
||||
case dns_trust_ultimate:
|
||||
rdataset->ttl = 0;
|
||||
|
|
@ -972,7 +982,7 @@ new_adbentry(dns_adb_t *adb, const isc_sockaddr_t *addr, isc_stdtime_t now) {
|
|||
.quota = adb->quota,
|
||||
.references = ISC_REFCOUNT_INITIALIZER(1),
|
||||
.adb = dns_adb_ref(adb),
|
||||
.expires = now + ADB_ENTRY_WINDOW,
|
||||
.expires = now + dns_adb_entrywindow,
|
||||
.loop = isc_loop_ref(isc_loop()),
|
||||
.magic = DNS_ADBENTRY_MAGIC,
|
||||
};
|
||||
|
|
@ -2018,6 +2028,10 @@ post_copy:
|
|||
find->cbarg = cbarg;
|
||||
}
|
||||
|
||||
if (wanted_fetches) {
|
||||
find->options |= DNS_ADBFIND_STARTEDFETCH;
|
||||
}
|
||||
|
||||
*findp = find;
|
||||
|
||||
UNLOCK(&adbname->lock);
|
||||
|
|
|
|||
|
|
@ -194,6 +194,10 @@ struct dns_adbfind {
|
|||
*/
|
||||
#define DNS_ADBFIND_STATICSTUB 0x00001000
|
||||
#define DNS_ADBFIND_NOVALIDATE 0x00002000
|
||||
/*%
|
||||
* This specific find created a fetch
|
||||
*/
|
||||
#define DNS_ADBFIND_STARTEDFETCH 0x00010000
|
||||
|
||||
/*%
|
||||
* The answers to queries come back as a list of these.
|
||||
|
|
|
|||
|
|
@ -1087,6 +1087,9 @@ set_stats(dns_resolver_t *res, isc_statscounter_t counter, uint64_t val) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
waiting_for_fetch(fetchctx_t *fctx, const dns_name_t *name,
|
||||
dns_rdatatype_t type, const dns_name_t *domain);
|
||||
static void
|
||||
valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
||||
dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset,
|
||||
|
|
@ -3340,9 +3343,10 @@ sort_finds(dns_adbfindlist_t *findlist, unsigned int bias) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Return true iff the ADB find has a pending fetch for 'type'. This is
|
||||
* used to find out whether we're in a loop, where a fetch is waiting for a
|
||||
* find which is waiting for that same fetch.
|
||||
* Return true iff the ADB find has an already pending fetch for 'type'. This
|
||||
* is used to find out whether we're in a loop, where a fetch is waiting for a
|
||||
* find which is waiting for that same fetch. So if the current find actually
|
||||
* started the fetch, we know it can't be a loop, so we returns false.
|
||||
*
|
||||
* Note: This could be done with either an equivalence check (e.g.,
|
||||
* query_pending == DNS_ADBFIND_INET) or with a bit check, as below. If
|
||||
|
|
@ -3361,7 +3365,11 @@ sort_finds(dns_adbfindlist_t *findlist, unsigned int bias) {
|
|||
* evil.
|
||||
*/
|
||||
static bool
|
||||
waiting_for(dns_adbfind_t *find, dns_rdatatype_t type) {
|
||||
already_waiting_for(dns_adbfind_t *find, dns_rdatatype_t type) {
|
||||
if ((find->options & DNS_ADBFIND_STARTEDFETCH) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case dns_rdatatype_a:
|
||||
return (find->query_pending & DNS_ADBFIND_INET) != 0;
|
||||
|
|
@ -3471,22 +3479,25 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
|
|||
* We don't know any of the addresses for this name.
|
||||
*
|
||||
* The find may be waiting on a resolver fetch for a server
|
||||
* address. We need to make sure it isn't waiting on *this*
|
||||
* address. We need to make sure it isn't waiting before *this*
|
||||
* fetch, because if it is, we won't be answering it and it
|
||||
* won't be answering us.
|
||||
*/
|
||||
if (waiting_for(find, fctx->type) && dns_name_equal(name, fctx->name)) {
|
||||
fctx->adberr++;
|
||||
if (already_waiting_for(find, fctx->type) &&
|
||||
dns_name_equal(name, fctx->name))
|
||||
{
|
||||
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
|
||||
ISC_LOG_INFO, "loop detected resolving '%s'",
|
||||
fctx->info);
|
||||
|
||||
fctx->adberr++;
|
||||
if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
|
||||
dns_adb_cancelfind(find);
|
||||
} else {
|
||||
dns_adb_destroyfind(&find);
|
||||
fetchctx_detach(&fctx);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -10126,12 +10137,27 @@ get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_samedomain(const dns_name_t *domain1, const dns_name_t *domain2) {
|
||||
if (domain1 == NULL && domain2 == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (domain1 == NULL || domain2 == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !dns_name_compare(domain1, domain2);
|
||||
}
|
||||
|
||||
static bool
|
||||
waiting_for_fetch(fetchctx_t *fctx, const dns_name_t *name,
|
||||
dns_rdatatype_t type) {
|
||||
dns_rdatatype_t type, const dns_name_t *domain) {
|
||||
while (fctx != NULL) {
|
||||
if (type == fctx->type && !dns_name_compare(name, fctx->name)) {
|
||||
return true;
|
||||
if (is_samedomain(domain, fctx->domain)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
fctx = fctx->parent;
|
||||
}
|
||||
|
|
@ -10181,18 +10207,30 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
|
|||
|
||||
log_fetch(name, type);
|
||||
|
||||
if (waiting_for_fetch(parent, name, type)) {
|
||||
/*
|
||||
* This fetch loop detection enable to guard against loop scenarios
|
||||
* where the DNSSEC is involved. See
|
||||
* `4d307ac67a0e3f9831c9a4e66ac481e2f9ceebb5`. This is a complementary
|
||||
* detection with the ADB lookup loop detection (in `findname()`).
|
||||
*/
|
||||
if (waiting_for_fetch(parent, name, type, domain)) {
|
||||
if (isc_log_wouldlog(ISC_LOG_INFO)) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE + 1];
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
char domainbuf[DNS_NAME_FORMATSIZE + 1] = { 0 };
|
||||
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
|
||||
if (domain != NULL) {
|
||||
dns_name_format(domain, domainbuf,
|
||||
sizeof(domainbuf));
|
||||
}
|
||||
|
||||
isc_log_write(DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(2),
|
||||
"fetch loop detected resolving '%s/%s'",
|
||||
namebuf, typebuf);
|
||||
"fetch loop detected resolving '%s/%s "
|
||||
"(in '%s'?)",
|
||||
namebuf, typebuf, domainbuf);
|
||||
}
|
||||
return DNS_R_LOOPDETECTED;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue