ret=0
delv_with_opts -i +ns +qmin +hint=../common/root.hint a a.example > delv.out.test$n || ret=1
grep -q '; authoritative' delv.out.test$n || ret=1
- grep -q '_.example' delv.out.test$n || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
ret=0
delv_with_opts -a ns1/anchor.dnskey +root +ns +qmin +hint=../common/root.hint a a.example > delv.out.test$n || ret=1
grep -q '; fully validated' delv.out.test$n || ret=1
- grep -q '_.example' delv.out.test$n || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
sleep 1
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
-ADDR _.boing.good.
-ADDR _.zoop.boing.good.
ADDR a.bit.longer.ns.name.good.
ADDR a.bit.longer.ns.name.good.
ADDR ns2.good.
ADDR ns3.good.
ADDR ns3.good.
+NS boing.good.
+NS zoop.boing.good.
__EOF
cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
-ADDR _.ptang.zoop.boing.good.
-ADDR _.icky.ptang.zoop.boing.good.
+NS ptang.zoop.boing.good.
+NS icky.ptang.zoop.boing.good.
__EOF
cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
-ADDR _.icky.icky.ptang.zoop.boing.good.
+NS icky.icky.ptang.zoop.boing.good.
ADDR icky.icky.icky.ptang.zoop.boing.good.
__EOF
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
sleep 1
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
-ADDR _.boing.bad.
-ADDR _.zoop.boing.bad.
ADDR a.bit.longer.ns.name.bad.
ADDR a.bit.longer.ns.name.bad.
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
ADDR ns2.bad.
ADDR ns3.bad.
ADDR ns3.bad.
+NS boing.bad.
__EOF
cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
-ADDR _.ptang.zoop.boing.bad.
-ADDR _.icky.ptang.zoop.boing.bad.
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
__EOF
cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
-ADDR _.icky.icky.ptang.zoop.boing.bad.
ADDR icky.icky.icky.ptang.zoop.boing.bad.
__EOF
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "icky.icky.icky.ptang.zoop.boing.ugly. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
sleep 1
-
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
-ADDR _.boing.ugly.
ADDR a.bit.longer.ns.name.ugly.
ADDR a.bit.longer.ns.name.ugly.
ADDR icky.icky.icky.ptang.zoop.boing.ugly.
ADDR ns2.ugly.
ADDR ns3.ugly.
ADDR ns3.ugly.
+NS boing.ugly.
__EOF
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - > /dev/null || ret=1
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - > /dev/null || ret=1
$RNDCCMD 10.53.0.7 flush
n=$((n+1))
-echo_i "information that minimization was unsuccessful for .ugly is logged ($n)"
+echo_i "information that minimization was unsuccessful for .ugly is logged in relaxed mode ($n)"
ret=0
wait_for_log 5 "success resolving 'icky.icky.icky.ptang.zoop.boing.ugly/A' after disabling qname minimization" ns7/named.run > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
sleep 1
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
-ADDR _.b.stale.
ADDR ns.b.stale.
ADDR ns2.stale.
+NS b.stale.
__EOF
test -f ans3/query.log && ret=1
sort ans4/query.log > ans4/query.log.sorted
sleep 1
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
-ADDR _.b.stale.
+NS b.stale.
__EOF
test -f ans3/query.log && ret=1
sort ans4/query.log > ans4/query.log.sorted
:tags: query
:short: Controls QNAME minimization behavior in the BIND 9 resolver.
- When this is set to ``strict``, BIND follows the QNAME
- minimization algorithm to the letter, as specified in :rfc:`7816`.
+ When this is set to ``strict``, BIND follows the QNAME minimization
+ algorithm to the letter, as specified in :rfc:`7816`.
Setting this option to ``relaxed`` causes BIND to fall back to
- normal (non-minimized) query mode when it receives either NXDOMAIN or
- other unexpected responses (e.g., SERVFAIL, improper zone cut,
- REFUSED) to a minimized query. A resolver can use a leading
- underscore, like ``_.example.com``, in an attempt to improve
- interoperability. (See :rfc:`7816` section 3.)
+ normal (non-minimized) query mode when it receives either NXDOMAIN
+ or other unexpected responses (e.g., SERVFAIL, improper zone
+ cut, REFUSED) to a minimized query.
+
+ In ``relaxed`` mode ``named`` makes NS queries for ``<domain>`` as it
+ walks down the tree.
``disabled`` disables QNAME minimization completely.
``off`` is a synonym for ``disabled``.
- The current default is ``relaxed``, but it
- may be changed to ``strict`` in a future release.
+ The current default is ``relaxed``, but it may be changed to
+ ``strict`` in a future release.
.. namedconf:statement:: tkey-gssapi-keytab
:tags: security
/* RESERVED ECS 0x00001000 */
/* RESERVED ECS 0x00002000 */
/* RESERVED TCPCLIENT 0x00004000 */
-#define DNS_FETCHOPT_NOCACHED 0x00008000 /*%< Force cache update. */
-#define DNS_FETCHOPT_QMINIMIZE \
- 0x00010000 /*%< Use qname \
- * minimization. */
-#define DNS_FETCHOPT_NOFOLLOW \
- 0x00020000 /*%< Don't follow \
- * delegations */
-#define DNS_FETCHOPT_QMIN_STRICT \
- 0x00040000 /*%< Do not work around \
- * servers that return \
- * errors on non-empty \
- * terminals. */
-#define DNS_FETCHOPT_QMIN_USE_A \
- 0x00080000 /*%< Use A type queries \
- * instead of NS when \
- * doing minimization */
-#define DNS_FETCHOPT_QMIN_SKIP_IP6A \
- 0x00100000 /*%< Skip some labels \
- * when doing qname \
- * minimization on \
+#define DNS_FETCHOPT_NOCACHED 0x00008000 /*%< Force cache update. */
+#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname minimization. */
+#define DNS_FETCHOPT_NOFOLLOW \
+ 0x00020000 /*%< Don't retrieve the NS RRset from the child zone when a \
+ * delegation is returned in response to a NS query. */
+#define DNS_FETCHOPT_QMIN_STRICT \
+ 0x00040000 /*%< Do not work around servers that return errors on \
+ * non-empty terminals. */
+#define DNS_FETCHOPT_QMIN_SKIP_IP6A \
+ 0x00080000 /*%< Skip some labels when doing qname minimization on \
* ip6.arpa. */
-#define DNS_FETCHOPT_NOFORWARD \
- 0x00200000 /*%< Do not use forwarders \
- * if possible. */
+#define DNS_FETCHOPT_NOFORWARD \
+ 0x00100000 /*%< Do not use forwarders if possible. */
+/* UNUSED 0x00200000 */
/* Reserved in use by adb.c 0x00400000 */
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
#define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000
static const dns_name_t ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data,
ip6_arpa_offsets);
-static unsigned char underscore_data[] = "\001_";
-static unsigned char underscore_offsets[] = { 0 };
-static const dns_name_t underscore_name =
- DNS_NAME_INITNONABSOLUTE(underscore_data, underscore_offsets);
-
static void
dns_resolver__destroy(dns_resolver_t *res);
static isc_result_t
}
/*
- * In "_ A" mode we're asking for _.domain -
- * resolver by default will follow delegations
- * then, we don't want that.
+ * Turn on NOFOLLOW in relaxed mode so that QNAME minimisation
+ * doesn't cause additional queries to resolve the target of the
+ * QNAME minimisation request when a referral is returned. This
+ * will also reduce the impact of mis-matched NS RRsets where
+ * the child's NS RRset is garbage. If a delegation is
+ * discovered DNS_R_DELEGATION will be returned to resume_qmin.
*/
- if ((options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
+ if ((options & DNS_FETCHOPT_QMIN_STRICT) == 0) {
options |= DNS_FETCHOPT_NOFOLLOW;
}
goto cleanup;
case DNS_R_NXDOMAIN:
case DNS_R_NCACHENXDOMAIN:
- /*
- * If we're doing "_ A"-style minimization we can get
- * NX answer to minimized query - we need to continue then.
- */
- if ((fctx->options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
- break;
- }
- FALLTHROUGH;
case DNS_R_FORMERR:
case DNS_R_REMOTEFORMERR:
case ISC_R_FAILURE:
}
break;
default:
+ /*
+ * When DNS_FETCHOPT_NOFOLLOW is set and a delegation
+ * was discovered, DNS_R_DELEGATION is returned and is
+ * processed here.
+ */
break;
}
case DNS_R_CHASEDSSERVERS:
break;
case DNS_R_DELEGATION:
- /* With NOFOLLOW we want to pass the result code
+ /*
+ * With NOFOLLOW we want to pass the result code.
*/
if ((fctx->options & DNS_FETCHOPT_NOFOLLOW) == 0) {
result = ISC_R_SUCCESS;
dns_fixedname_t fname;
dns_name_t *name = dns_fixedname_initname(&fname);
dns_name_split(fctx->name, fctx->qmin_labels, NULL, name);
- if ((fctx->options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
- isc_buffer_t dbuf;
- dns_fixedname_t tmpname;
- dns_name_t *tname = dns_fixedname_initname(&tmpname);
- char ndata[DNS_NAME_MAXWIRE];
-
- isc_buffer_init(&dbuf, ndata, DNS_NAME_MAXWIRE);
- dns_fixedname_init(&tmpname);
- result = dns_name_concatenate(&underscore_name, name,
- tname, &dbuf);
- if (result == ISC_R_SUCCESS) {
- dns_name_copy(tname, fctx->qminname);
- }
- fctx->qmintype = dns_rdatatype_a;
- } else {
- dns_name_copy(name, fctx->qminname);
- fctx->qmintype = dns_rdatatype_ns;
- }
+ dns_name_copy(name, fctx->qminname);
+ fctx->qmintype = dns_rdatatype_ns;
fctx->minimized = true;
} else {
/* Minimization is done, we'll ask for whole qname */
DNS_FETCHOPT_QMIN_SKIP_IP6A;
if (client->view->qmin_strict) {
client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT;
- } else {
- client->query.fetchoptions |= DNS_FETCHOPT_QMIN_USE_A;
}
}