From 0698158eb004369e0afeeebda42e704a6ebed44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Wed, 9 May 2018 12:02:11 +0200 Subject: [PATCH 01/15] QNAME minimization --- bin/named/config.c | 2 + bin/named/server.c | 10 + .../system/qname-minimization/ans2/ans.py | 206 ++++++++++++++++++ bin/tests/system/qname-minimization/clean.sh | 17 ++ .../qname-minimization/ns1/named.conf.in | 29 +++ .../system/qname-minimization/ns1/root.db | 32 +++ .../qname-minimization/ns3/named.conf.in | 41 ++++ .../qname-minimization/ns4/named.conf.in | 41 ++++ .../qname-minimization/ns5/named.conf.in | 41 ++++ bin/tests/system/qname-minimization/setup.sh | 20 ++ bin/tests/system/qname-minimization/tests.sh | 138 ++++++++++++ bin/tests/system/testsock.pl | 0 doc/misc/options | 2 + lib/dns/include/dns/resolver.h | 9 +- lib/dns/include/dns/view.h | 2 + lib/dns/resolver.c | 162 +++++++++++++- lib/dns/view.c | 2 + lib/isccfg/namedconf.c | 2 + lib/ns/query.c | 9 + util/copyrights | 9 + 20 files changed, 762 insertions(+), 12 deletions(-) create mode 100755 bin/tests/system/qname-minimization/ans2/ans.py create mode 100644 bin/tests/system/qname-minimization/clean.sh create mode 100644 bin/tests/system/qname-minimization/ns1/named.conf.in create mode 100644 bin/tests/system/qname-minimization/ns1/root.db create mode 100644 bin/tests/system/qname-minimization/ns3/named.conf.in create mode 100644 bin/tests/system/qname-minimization/ns4/named.conf.in create mode 100644 bin/tests/system/qname-minimization/ns5/named.conf.in create mode 100644 bin/tests/system/qname-minimization/setup.sh create mode 100755 bin/tests/system/qname-minimization/tests.sh mode change 100644 => 100755 bin/tests/system/testsock.pl diff --git a/bin/named/config.c b/bin/named/config.c index eb78c2cddc..7dd9d9e61a 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -185,6 +185,8 @@ options {\n\ provide-ixfr true;\n\ query-source address *;\n\ query-source-v6 address *;\n\ + qname-minimization no;\n\ + qname-minimization-strict no;\n\ recursion true;\n\ request-expire true;\n\ request-ixfr true;\n\ diff --git a/bin/named/server.c b/bin/named/server.c index 1f827a8700..c5dc11cd42 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -4639,6 +4639,16 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, INSIST(result == ISC_R_SUCCESS); view->recursion = cfg_obj_asboolean(obj); + obj = NULL; + result = named_config_get(maps, "qname-minimization", &obj); + INSIST(result == ISC_R_SUCCESS); + view->qminimization = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "qname-minimization-strict", &obj); + INSIST(result == ISC_R_SUCCESS); + view->qmin_strict = cfg_obj_asboolean(obj); + obj = NULL; result = named_config_get(maps, "auth-nxdomain", &obj); INSIST(result == ISC_R_SUCCESS); diff --git a/bin/tests/system/qname-minimization/ans2/ans.py b/bin/tests/system/qname-minimization/ans2/ans.py new file mode 100755 index 0000000000..036158e5f6 --- /dev/null +++ b/bin/tests/system/qname-minimization/ans2/ans.py @@ -0,0 +1,206 @@ +############################################################################ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. +############################################################################ + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import time +import functools + +import dns, dns.message, dns.query +from dns.rdatatype import * +from dns.rdataclass import * +from dns.rcode import * +from dns.name import * + + +# Log query to file +def logquery(type, qname): + with open("qlog", "a") as f: + f.write("%s %s\n", type, qname) + +############################################################################ +# Respond to a DNS query. +# For good. it serves: +# ns2.good. IN A 10.53.0.2 +# icky.icky.icky.ptang.zoop.boing.good. A 192.0.2.1 +# it responds properly (with NODATA empty response) to non-empty terminals +# +# For slow. it works the same as for good., but each response is delayed by 400 miliseconds +# +# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals +# +# For 1.0.0.2.ip6.arpa it serves +# 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. IN PTR nee.com. +# 1.0.0.2.ip6.arpa. IN NS ns2.good +# ip6.arpa. IN NS ns2.good +############################################################################ +def create_response(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + lqname = qname.lower() + labels = lqname.split('.') + + # get qtype + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + bad = False + slow = False + + # log this query + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, lqname)) + print("%s %s" % (typename, lqname), end=" ") + + r = dns.message.make_response(m) + r.set_rcode(NOERROR) + + if lqname.endswith("1.0.0.2.ip6.arpa."): + # Direct query - give direct answer + if lqname == "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa." and rrtype == PTR: + # Direct query - give direct answer + r.answer.append(dns.rrset.from_text("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", 1, IN, PTR, "nee.com.")) + elif lqname == "1.0.0.2.ip6.arpa." and rrtype == NS: + # NS query at the apex + r.answer.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 1, IN, NS, "ns2.good.")) + elif "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.".endswith(lqname): + # NODATA answer + r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 1, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + else: + # NXDOMAIN + r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 1, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.set_rcode(NXDOMAIN) + return r + elif lqname.endswith("ip6.arpa."): + if lqname == "ip6.arpa." and rrtype == NS: + # NS query at the apex + r.answer.append(dns.rrset.from_text("ip6.arpa.", 1, IN, NS, "ns2.good.")) + elif "1.0.0.2.ip6.arpa.".endswith(lqname): + # NODATA answer + r.authority.append(dns.rrset.from_text("ip6.arpa.", 1, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + else: + # NXDOMAIN + r.authority.append(dns.rrset.from_text("ip6.arpa.", 1, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.set_rcode(NXDOMAIN) + return r + elif lqname.endswith("bad."): + bad = True + suffix = "bad." + lqname = lqname[:-4] + elif lqname.endswith("good."): + suffix = "good." + lqname = lqname[:-5] + elif lqname.endswith("slow."): + slow = True + suffix = "slow." + lqname = lqname[:-5] + else: + r.set_rcode(REFUSED) + return r + + # Good/bad differs only in how we treat non-empty terminals + if lqname == "icky.icky.icky.ptang.zoop.boing." and rrtype == A: + r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.1")) + elif lqname == "" and rrtype == NS: + r.answer.append(dns.rrset.from_text(suffix, 1, IN, NS, "ns2." + suffix)) + elif lqname == "ns2." and rrtype == A: + r.answer.append(dns.rrset.from_text("ns2."+suffix, 1, IN, A, "10.53.0.2")) + elif lqname == "ns2." and rrtype == AAAA: + r.answer.append(dns.rrset.from_text("ns2."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::2")) + else: + r.authority.append(dns.rrset.from_text(suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + if bad or not "icky.icky.icky.ptang.zoop.boing.".endswith(lqname): + r.set_rcode(NXDOMAIN) + if slow: + time.sleep(0.4) + return r + + +def sigterm(signum, frame): + print ("Shutting down now...") + os.remove('ans.pid') + running = False + sys.exit(0) + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4 = "10.53.0.2" +ip6 = "fd92:7065:b8e:ffff::2" + +try: port=int(os.environ['PORT']) +except: port=5300 + +query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_socket.bind((ip4, port)) + +havev6 = True +try: + query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + try: + query6_socket.bind((ip6, port)) + except: + query6_socket.close() + havev6 = False +except: + havev6 = False + +signal.signal(signal.SIGTERM, sigterm) + +f = open('ans.pid', 'w') +pid = os.getpid() +print (pid, file=f) +f.close() + +running = True + +print ("Listening on %s port %d" % (ip4, port)) +if havev6: + print ("Listening on %s port %d" % (ip6, port)) +print ("Ctrl-c to quit") + +if havev6: + input = [query4_socket, query6_socket] +else: + input = [query4_socket] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == query4_socket or s == query6_socket: + print ("Query received on %s" % + (ip4 if s == query4_socket else ip6), end=" ") + # Handle incoming queries + msg = s.recvfrom(65535) + rsp = create_response(msg[0]) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + else: + print("NO RESPONSE") + if not running: + break diff --git a/bin/tests/system/qname-minimization/clean.sh b/bin/tests/system/qname-minimization/clean.sh new file mode 100644 index 0000000000..eaff4210bb --- /dev/null +++ b/bin/tests/system/qname-minimization/clean.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +rm -f ns*/named.conf +rm -f */named.memstats +rm -f */named.run +rm -f dig.out.* +rm -f ns*/named.lock +rm -f ans2/query.log diff --git a/bin/tests/system/qname-minimization/ns1/named.conf.in b/bin/tests/system/qname-minimization/ns1/named.conf.in new file mode 100644 index 0000000000..7188e3c372 --- /dev/null +++ b/bin/tests/system/qname-minimization/ns1/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +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; }; + listen-on-v6 { none; }; + recursion no; + notify yes; +}; + +zone "." { + type master; + file "root.db"; +}; diff --git a/bin/tests/system/qname-minimization/ns1/root.db b/bin/tests/system/qname-minimization/ns1/root.db new file mode 100644 index 0000000000..83f157f8f0 --- /dev/null +++ b/bin/tests/system/qname-minimization/ns1/root.db @@ -0,0 +1,32 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; 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 http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +. IN SOA wpk.isc.org. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +ip6.arpa. NS ns2.good. + +good. NS ns2.good. +ns2.good. A 10.53.0.2 + +bad. NS ns2.bad. +ns2.bad. A 10.53.0.2 + +slow NS ns2.slow. +ns2.slow. A 10.53.0.2 + +horrible. NS ns2.horrible. +ns2.horrible. A 10.53.0.2 diff --git a/bin/tests/system/qname-minimization/ns3/named.conf.in b/bin/tests/system/qname-minimization/ns3/named.conf.in new file mode 100644 index 0000000000..2a6dce9c13 --- /dev/null +++ b/bin/tests/system/qname-minimization/ns3/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +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; }; + listen-on-v6 { none; }; + recursion yes; + qname-minimization no; + qname-minimization-strict no; + querylog yes; + resolver-query-timeout 30; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; diff --git a/bin/tests/system/qname-minimization/ns4/named.conf.in b/bin/tests/system/qname-minimization/ns4/named.conf.in new file mode 100644 index 0000000000..403fc0fd15 --- /dev/null +++ b/bin/tests/system/qname-minimization/ns4/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +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; }; + listen-on-v6 { none; }; + recursion yes; + qname-minimization yes; + qname-minimization-strict yes; + querylog yes; + resolver-query-timeout 30; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; diff --git a/bin/tests/system/qname-minimization/ns5/named.conf.in b/bin/tests/system/qname-minimization/ns5/named.conf.in new file mode 100644 index 0000000000..f570b88835 --- /dev/null +++ b/bin/tests/system/qname-minimization/ns5/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + qname-minimization yes; + qname-minimization-strict no; + querylog yes; + resolver-query-timeout 30; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; diff --git a/bin/tests/system/qname-minimization/setup.sh b/bin/tests/system/qname-minimization/setup.sh new file mode 100644 index 0000000000..0294ed7487 --- /dev/null +++ b/bin/tests/system/qname-minimization/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh -e +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +$SHELL clean.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf diff --git a/bin/tests/system/qname-minimization/tests.sh b/bin/tests/system/qname-minimization/tests.sh new file mode 100755 index 0000000000..84ab0a4834 --- /dev/null +++ b/bin/tests/system/qname-minimization/tests.sh @@ -0,0 +1,138 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" +CLEANQL="rm -f ans2/query.log" +status=0 +n=0 + +n=`expr $n + 1` +echo_i "query for .good is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.3 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.3 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.good." | diff ans2/query.log - > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .bad is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.3 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.3 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans2/query.log - > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .slow is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.3 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.3 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.slow." | diff ans2/query.log - > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .good is properly minimized when qname-minimization is on ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.4 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.4 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +NS boing.good. +NS zoop.boing.good. +NS ptang.zoop.boing.good. +NS icky.ptang.zoop.boing.good. +NS icky.icky.ptang.zoop.boing.good. +A icky.icky.icky.ptang.zoop.boing.good. +__EOF +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .bad fails when qname-minimization is on and in strict mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.4 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.4 > dig.out.test$n +grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +echo "NS boing.bad." | diff ans2/query.log - > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .bad succeds when qname-minimization is on and not in strict mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.5 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +NS boing.bad. +NS zoop.boing.bad. +NS ptang.zoop.boing.bad. +NS icky.ptang.zoop.boing.bad. +NS icky.icky.ptang.zoop.boing.bad. +A icky.icky.icky.ptang.zoop.boing.bad. +__EOF +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .slow is properly minimized when qname-minimization is on ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.4 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.4 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +NS boing.slow. +NS zoop.boing.slow. +NS ptang.zoop.boing.slow. +NS icky.ptang.zoop.boing.slow. +NS icky.icky.ptang.zoop.boing.slow. +A icky.icky.icky.ptang.zoop.boing.slow. +__EOF +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for .ip6.arpa succeds and skips on boundaries when qname-minimization is on ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.4 flush +$DIG $DIGOPTS -x 2001:4f8::1 @10.53.0.4 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +NS 1.0.0.2.ip6.arpa. +NS 8.f.4.0.1.0.0.2.ip6.arpa. +NS 0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +NS 0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +NS 0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +__EOF +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/testsock.pl b/bin/tests/system/testsock.pl old mode 100644 new mode 100755 diff --git a/doc/misc/options b/doc/misc/options index e2bcd1eb9e..51e97d563e 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -264,6 +264,8 @@ options { preferred-glue ; prefetch [ ]; provide-ixfr ; + qname-minimization ; + qname-minimization-strict ; query-source ( ( [ address ] ( | * ) [ port ( | * ) ] ) | ( [ [ address ] ( | * ) ] port ( | * ) ) ) [ dscp ]; diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 17418424ec..fbd90a6689 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -105,6 +105,13 @@ typedef enum { /* RESERVED ECS 0x2000 */ /* RESERVED TCPCLIENT 0x4000 */ #define DNS_FETCHOPT_NOCACHED 0x8000 /*%< Force cache update. */ +#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname minimization. */ +#define DNS_FETCHOPT_QMIN_STRICT 0x00020000 /*%< Do not work around servers that + return errors on non-empty + terminals. */ +#define DNS_FETCHOPT_QMIN_SKIP_ON_IP6A 0x00040000 /*%< Skip some labels when + doing qname minimization on + ip6.arpa. */ /* Reserved in use by adb.c 0x00400000 */ #define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 @@ -267,7 +274,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, const dns_name_t *domain, dns_rdataset_t *nameservers, dns_forwarders_t *forwarders, - const isc_sockaddr_t *client, isc_uint16_t id, + const isc_sockaddr_t *client, dns_messageid_t id, unsigned int options, unsigned int depth, isc_counter_t *qc, isc_task_t *task, isc_taskaction_t action, void *arg, diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 3fd4959506..3ec8aba42f 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -115,6 +115,8 @@ struct dns_view { dns_order_t * order; dns_fwdtable_t * fwdtable; isc_boolean_t recursion; + isc_boolean_t qminimization; + isc_boolean_t qmin_strict; isc_boolean_t auth_nxdomain; isc_boolean_t use_glue_cache; isc_boolean_t minimal_any; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 840f99ac97..1898021672 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -258,8 +258,8 @@ struct fetchctx { /*% Not locked. */ unsigned int magic; dns_resolver_t * res; - dns_name_t name; - dns_rdatatype_t type; + dns_name_t fullname; + dns_rdatatype_t fulltype; unsigned int options; unsigned int bucketnum; unsigned int dbucketnum; @@ -275,6 +275,7 @@ struct fetchctx { isc_event_t control_event; ISC_LINK(struct fetchctx) link; ISC_LIST(dns_fetchevent_t) events; + /*% Locked by task event serialization. */ dns_name_t domain; dns_rdataset_t nameservers; @@ -304,6 +305,11 @@ struct fetchctx { isc_boolean_t ns_ttl_ok; isc_uint32_t ns_ttl; isc_counter_t * qc; + isc_boolean_t minimized; + unsigned int qmin_labels; + isc_boolean_t ip6arpaskip; + dns_name_t name; + dns_rdatatype_t type; /*% * The number of events we're waiting for. @@ -554,6 +560,11 @@ void dns_resolver_setfuzzing() { } #endif +static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA"; +static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 }; +static const dns_name_t ip6_arpa = + DNS_NAME_INITABSOLUTE(ip6_arpa_data, ip6_arpa_offsets); + static void destroy(dns_resolver_t *res); static void empty_bucket(dns_resolver_t *res); static isc_result_t resquery_send(resquery_t *query); @@ -561,6 +572,7 @@ static void resquery_response(isc_task_t *task, isc_event_t *event); static void resquery_connected(isc_task_t *task, isc_event_t *event); static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache); +void fctx_minimize_qname(fetchctx_t *fctx); static void fctx_destroy(fetchctx_t *fctx); static isc_boolean_t fctx_unlink(fetchctx_t *fctx); static isc_result_t ncache_adderesult(dns_message_t *message, @@ -749,6 +761,12 @@ rctx_referral(respctx_t *rctx); static isc_result_t rctx_answer_none(respctx_t *rctx); +static void +rctx_follow_referral(respctx_t *rctx); + +static isc_result_t +rctx_answer_minimized(respctx_t *rctx); + static void rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo, isc_result_t result); @@ -4136,6 +4154,7 @@ fctx_destroy(fetchctx_t *fctx) { dns_name_free(&fctx->domain, fctx->mctx); if (dns_rdataset_isassociated(&fctx->nameservers)) dns_rdataset_disassociate(&fctx->nameservers); + dns_name_free(&fctx->fullname, fctx->mctx); dns_name_free(&fctx->name, fctx->mctx); dns_db_detach(&fctx->cache); dns_adb_detach(&fctx->adb); @@ -4514,9 +4533,14 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, result = dns_name_dup(name, mctx, &fctx->name); if (result != ISC_R_SUCCESS) goto cleanup_info; + dns_name_init(&fctx->fullname, NULL); + result = dns_name_dup(name, mctx, &fctx->fullname); + if (result != ISC_R_SUCCESS) + goto cleanup_name; dns_name_init(&fctx->domain, NULL); dns_rdataset_init(&fctx->nameservers); + fctx->fulltype = type; fctx->type = type; fctx->options = options; /* @@ -4532,6 +4556,9 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, fctx->want_shutdown = ISC_FALSE; fctx->cloned = ISC_FALSE; fctx->depth = depth; + fctx->minimized = isc_boolean_false; + fctx->ip6arpaskip = isc_boolean_false; + fctx->qmin_labels = 1; ISC_LIST_INIT(fctx->queries); ISC_LIST_INIT(fctx->finds); ISC_LIST_INIT(fctx->altfinds); @@ -4635,12 +4662,12 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, */ result = dns_name_dup(fname, mctx, &fctx->domain); if (result != ISC_R_SUCCESS) - goto cleanup_name; + goto cleanup_fullname; } } else { result = dns_name_dup(domain, mctx, &fctx->domain); if (result != ISC_R_SUCCESS) - goto cleanup_name; + goto cleanup_fullname; dns_rdataset_clone(nameservers, &fctx->nameservers); fctx->ns_ttl = fctx->nameservers.ttl; fctx->ns_ttl_ok = ISC_TRUE; @@ -4726,6 +4753,15 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, ISC_LINK_INIT(fctx, link); fctx->magic = FCTX_MAGIC; + /* + * If qname minimization is enabled we need to trim + * the name in fctx to proper length. + */ + if (options & DNS_FETCHOPT_QMINIMIZE) { + fctx->ip6arpaskip = (options & DNS_FETCHOPT_QMIN_SKIP_ON_IP6A) && dns_name_issubdomain(&fctx->name, &ip6_arpa); + fctx_minimize_qname(fctx); + } + ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link); LOCK(&res->nlock); @@ -4754,6 +4790,9 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, if (dns_rdataset_isassociated(&fctx->nameservers)) dns_rdataset_disassociate(&fctx->nameservers); + cleanup_fullname: + dns_name_free(&fctx->fullname, mctx); + cleanup_name: dns_name_free(&fctx->name, mctx); @@ -5636,6 +5675,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, unsigned int valoptions = 0; isc_boolean_t checknta = ISC_TRUE; + FCTXTRACE("cache_name"); + /* * The appropriate bucket lock must be held. */ @@ -6459,12 +6500,10 @@ check_related(void *arg, const dns_name_t *addname, dns_rdatatype_t type) { #ifndef CHECK_FOR_GLUE_IN_ANSWER #define CHECK_FOR_GLUE_IN_ANSWER 0 #endif -#if CHECK_FOR_GLUE_IN_ANSWER static isc_result_t check_answer(void *arg, const dns_name_t *addname, dns_rdatatype_t type) { return (check_section(arg, addname, type, DNS_SECTION_ANSWER)); } -#endif static isc_boolean_t is_answeraddress_allowed(dns_view_t *view, dns_name_t *name, @@ -7752,7 +7791,12 @@ rctx_answer(respctx_t *rctx) { fetchctx_t *fctx = rctx->fctx; resquery_t *query = rctx->query; - if ((fctx->rmessage->flags & DNS_MESSAGEFLAG_AA) != 0 || + if (fctx->minimized) { + result = rctx_answer_minimized(rctx); + if (result != ISC_R_SUCCESS) { + FCTXTRACE3("rctx_answer_minimized", result); + } + } else if ((fctx->rmessage->flags & DNS_MESSAGEFLAG_AA) != 0 || ISFORWARDER(query->addrinfo)) { result = rctx_answer_positive(rctx); @@ -8475,6 +8519,16 @@ rctx_answer_none(respctx_t *rctx) { return (rctx->result); } + /* + * If we're doing qname minimization this is an empty non-terminal, add + * the next label to query and restart it. + */ + if (fctx->minimized && + (fctx->rmessage->rcode == dns_rcode_noerror || + !(fctx->options & DNS_FETCHOPT_QMIN_STRICT))) { + return rctx_answer_minimized(rctx); + } + /* * Since we're not doing a referral, we don't want to cache any * NS RRs we may have found. @@ -8842,6 +8896,10 @@ rctx_referral(respctx_t *rctx) { check_answer, fctx); } #endif + if (fctx->minimized) { + (void)dns_rdataset_additionaldata(rctx->ns_rdataset, + check_answer, fctx); + } fctx->attributes &= ~FCTX_ATTR_GLUING; /* @@ -8887,6 +8945,39 @@ rctx_referral(respctx_t *rctx) { log_ns_ttl(fctx, "DELEGATION"); rctx->result = DNS_R_DELEGATION; + rctx_follow_referral(rctx); + if (rctx->fctx->minimized) { + /* + * Reset the value + */ + fctx->qmin_labels = 1; + fctx_minimize_qname(rctx->fctx); + } + return (ISC_R_COMPLETE); +} + +/* + * rctx_answer_minimized(): + * Handles a positive response to a qname-minimized query. + */ +static isc_result_t +rctx_answer_minimized(respctx_t *rctx) { + fetchctx_t *fctx = rctx->fctx; + + FCTXTRACE("rctx_answer_minimized"); + if (dns_rdataset_isassociated(&fctx->nameservers)) { + dns_rdataset_disassociate(&fctx->nameservers); + } + rctx->result = DNS_R_DELEGATION; + rctx_follow_referral(rctx); + fctx->qmin_labels++; + fctx_minimize_qname(rctx->fctx); + + return (ISC_R_SUCCESS); +} + +static void +rctx_follow_referral(respctx_t *rctx) { /* * Reinitialize 'rctx' to prepare for following the delegation: * set the get_nameservers and next_server flags appropriately and @@ -8903,8 +8994,6 @@ rctx_referral(respctx_t *rctx) { rctx->fctx->neterr = 0; rctx->fctx->badresp = 0; rctx->fctx->adberr = 0; - - return (ISC_R_COMPLETE); } /* @@ -10138,9 +10227,9 @@ fctx_match(fetchctx_t *fctx, const dns_name_t *name, dns_rdatatype_t type, ISC_LIST_EMPTY(fctx->events)) return (ISC_FALSE); - if (fctx->type != type || fctx->options != options) + if (fctx->fulltype != type || fctx->options != options) return (ISC_FALSE); - return (dns_name_equal(&fctx->name, name)); + return (dns_name_equal(&fctx->fullname, name)); } static inline void @@ -10164,6 +10253,57 @@ log_fetch(const dns_name_t *name, dns_rdatatype_t type) { "fetch: %s/%s", namebuf, typebuf); } +void +fctx_minimize_qname(fetchctx_t *fctx) { + /* XXXWPK TODO we should update info to show that this query is minimized */ + unsigned int dlabels, nlabels; + + dlabels = dns_name_countlabels(&fctx->domain); + nlabels = dns_name_countlabels(&fctx->fullname); + dns_name_free(&fctx->name, fctx->mctx); + dns_name_init(&fctx->name, NULL); + if (fctx->ip6arpaskip) { + /* + * For ip6.arpa we want to skip some of the labels, with boundaries + * at /16, /32, /48, /56, /64 and /128 + * in 'label count' terms that's equal to + * 7 11 15 17 19 35 + * We fix fctx->qmin_labels to point to the nearest boundary + */ + if (dlabels + fctx->qmin_labels < 7) { + fctx->qmin_labels = 7 - dlabels; + } else if (dlabels + fctx->qmin_labels < 11) { + fctx->qmin_labels = 11 - dlabels; + } else if (dlabels + fctx->qmin_labels < 15) { + fctx->qmin_labels = 15 - dlabels; + } else if (dlabels + fctx->qmin_labels < 17) { + fctx->qmin_labels = 17 - dlabels; + } else if (dlabels + fctx->qmin_labels < 19) { + fctx->qmin_labels = 19 - dlabels; + } else if (dlabels + fctx->qmin_labels > 19) { + fctx->qmin_labels = 35 - dlabels; + } + } + if (dlabels + fctx->qmin_labels < nlabels) { + /* + * We want to query for [qmin_labels from fctx->fullname] + fctx->domain + */ + dns_fixedname_t fname; + dns_fixedname_init(&fname); + dns_name_split(&fctx->fullname, + dlabels + fctx->qmin_labels, + NULL, dns_fixedname_name(&fname)); + dns_name_dup(dns_fixedname_name(&fname), fctx->mctx, &fctx->name); + fctx->type = dns_rdatatype_ns; + fctx->minimized = isc_boolean_true; + } else { + /* Minimization is done, we'll ask for whole qname */ + fctx->type = fctx->fulltype; + dns_name_dup(&fctx->fullname, fctx->mctx, &fctx->name); + fctx->minimized = isc_boolean_false; + } +} + isc_result_t dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, diff --git a/lib/dns/view.c b/lib/dns/view.c index 8fbdd7bf85..5dafdb5a1e 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -182,6 +182,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, * Initialize configuration data with default values. */ view->recursion = ISC_TRUE; + view->qminimization = ISC_FALSE; + view->qmin_strict = ISC_FALSE; view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ view->enablednssec = ISC_TRUE; view->enablevalidation = ISC_TRUE; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index d69051ca1e..2ac7146794 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1937,6 +1937,8 @@ view_clauses[] = { { "preferred-glue", &cfg_type_astring, 0 }, { "prefetch", &cfg_type_prefetch, 0 }, { "provide-ixfr", &cfg_type_boolean, 0 }, + { "qname-minimization", &cfg_type_boolean, 0 }, + { "qname-minimization-strict", &cfg_type_boolean, 0 }, /* * Note that the query-source option syntax is different * from the other -source options. diff --git a/lib/ns/query.c b/lib/ns/query.c index 27705c433c..037bc0653d 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -11106,6 +11106,15 @@ ns_query_start(ns_client_t *client) { } else if (!client->view->enablevalidation) client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; + if (client->view->qminimization) { + client->query.fetchoptions |= DNS_FETCHOPT_QMINIMIZE | + DNS_FETCHOPT_QMIN_SKIP_ON_IP6A; + if (client->view->qmin_strict) { + client->query.fetchoptions |= + DNS_FETCHOPT_QMIN_STRICT; + } + } + /* * Allow glue NS records to be added to the authority section * if the answer is secure. diff --git a/util/copyrights b/util/copyrights index a5ca23f99a..2e1f6ba4d5 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1729,6 +1729,15 @@ ./bin/tests/system/pkcs11ssl/setup.sh SH 2014,2016,2018 ./bin/tests/system/pkcs11ssl/tests.sh SH 2014,2016,2018 ./bin/tests/system/pkcs11ssl/usepkcs11 X 2014,2018 +./bin/tests/system/qname-minimization/ans2/ans.py PYTHON 2018 +./bin/tests/system/qname-minimization/clean.sh SH 2018 +./bin/tests/system/qname-minimization/ns1/named.conf.in CONF-C 2018 +./bin/tests/system/qname-minimization/ns1/root.db ZONE 2018 +./bin/tests/system/qname-minimization/ns3/named.conf.in CONF-C 2018 +./bin/tests/system/qname-minimization/ns4/named.conf.in CONF-C 2018 +./bin/tests/system/qname-minimization/ns5/named.conf.in CONF-C 2018 +./bin/tests/system/qname-minimization/setup.sh SH 2018 +./bin/tests/system/qname-minimization/tests.sh SH 2018 ./bin/tests/system/reclimit/README TXT.BRIEF 2014,2016,2017,2018 ./bin/tests/system/reclimit/ans2/ans.pl PERL 2014,2015,2016,2017,2018 ./bin/tests/system/reclimit/ans7/ans.pl PERL 2014,2016,2018 From dd7bb617be1ac4c09821f64a2d6e9bd6a54873d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Fri, 11 May 2018 12:27:56 +0200 Subject: [PATCH 02/15] - qname minimization: - make qname-minimization option tristate {strict,relaxed,disabled} - go straight for the record if we hit NXDOMAIN in relaxed mode - go straight for the record after 3 labels without new delegation or 7 labels total - use start of fetch (and not time of response) as 'now' time for querying cache for zonecut when following delegation. --- bin/named/config.c | 3 +- bin/named/server.c | 18 +- .../system/qname-minimization/ans2/ans.py | 25 ++- .../system/qname-minimization/ans3/ans.py | 175 +++++++++++++++++ .../system/qname-minimization/ans4/ans.py | 175 +++++++++++++++++ bin/tests/system/qname-minimization/clean.sh | 2 +- .../qname-minimization/ns5/named.conf.in | 3 +- .../{ns3 => ns6}/named.conf.in | 15 +- .../{ns4 => ns7}/named.conf.in | 15 +- bin/tests/system/qname-minimization/setup.sh | 4 +- bin/tests/system/qname-minimization/tests.sh | 177 +++++++++++++++--- lib/dns/adb.c | 8 + lib/dns/include/dns/resolver.h | 4 + lib/dns/resolver.c | 45 +++-- lib/isccfg/namedconf.c | 13 +- util/copyrights | 6 +- 16 files changed, 612 insertions(+), 76 deletions(-) create mode 100755 bin/tests/system/qname-minimization/ans3/ans.py create mode 100755 bin/tests/system/qname-minimization/ans4/ans.py rename bin/tests/system/qname-minimization/{ns3 => ns6}/named.conf.in (73%) rename bin/tests/system/qname-minimization/{ns4 => ns7}/named.conf.in (73%) diff --git a/bin/named/config.c b/bin/named/config.c index 7dd9d9e61a..3e4ceaea53 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -185,8 +185,7 @@ options {\n\ provide-ixfr true;\n\ query-source address *;\n\ query-source-v6 address *;\n\ - qname-minimization no;\n\ - qname-minimization-strict no;\n\ + qname-minimization relaxed;\n\ recursion true;\n\ request-expire true;\n\ request-ixfr true;\n\ diff --git a/bin/named/server.c b/bin/named/server.c index c5dc11cd42..38f9df1a0f 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -4642,12 +4642,18 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, obj = NULL; result = named_config_get(maps, "qname-minimization", &obj); INSIST(result == ISC_R_SUCCESS); - view->qminimization = cfg_obj_asboolean(obj); - - obj = NULL; - result = named_config_get(maps, "qname-minimization-strict", &obj); - INSIST(result == ISC_R_SUCCESS); - view->qmin_strict = cfg_obj_asboolean(obj); + const char * qminmode = cfg_obj_asstring(obj); + INSIST(qminmode != NULL); + if (!strcmp(qminmode, "strict")) { + view->qminimization = ISC_TRUE; + view->qmin_strict = ISC_TRUE; + } else if (!strcmp(qminmode, "relaxed")) { + view->qminimization = ISC_TRUE; + view->qmin_strict = ISC_FALSE; + } else { + view->qminimization = ISC_FALSE; + view->qmin_strict = ISC_FALSE; + } obj = NULL; result = named_config_get(maps, "auth-nxdomain", &obj); diff --git a/bin/tests/system/qname-minimization/ans2/ans.py b/bin/tests/system/qname-minimization/ans2/ans.py index 036158e5f6..1f44062d80 100755 --- a/bin/tests/system/qname-minimization/ans2/ans.py +++ b/bin/tests/system/qname-minimization/ans2/ans.py @@ -35,7 +35,9 @@ def logquery(type, qname): # Respond to a DNS query. # For good. it serves: # ns2.good. IN A 10.53.0.2 -# icky.icky.icky.ptang.zoop.boing.good. A 192.0.2.1 +# zoop.boing.good. NS ns3.good. +# ns3.good. IN A 10.53.0.3 +# too.many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. A 192.0.2.2 # it responds properly (with NODATA empty response) to non-empty terminals # # For slow. it works the same as for good., but each response is delayed by 400 miliseconds @@ -111,20 +113,33 @@ def create_response(msg): return r # Good/bad differs only in how we treat non-empty terminals - if lqname == "icky.icky.icky.ptang.zoop.boing." and rrtype == A: - r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.1")) + if lqname.endswith("zoop.boing."): + r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix)) + elif lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z." and rrtype == A: + r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2")) elif lqname == "" and rrtype == NS: r.answer.append(dns.rrset.from_text(suffix, 1, IN, NS, "ns2." + suffix)) elif lqname == "ns2." and rrtype == A: r.answer.append(dns.rrset.from_text("ns2."+suffix, 1, IN, A, "10.53.0.2")) elif lqname == "ns2." and rrtype == AAAA: r.answer.append(dns.rrset.from_text("ns2."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::2")) + elif lqname == "ns3." and rrtype == A: + r.answer.append(dns.rrset.from_text("ns3."+suffix, 1, IN, A, "10.53.0.3")) + elif lqname == "ns3." and rrtype == AAAA: + r.answer.append(dns.rrset.from_text("ns3."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::3")) + elif lqname == "a.bit.longer.ns.name." and rrtype == A: + r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, A, "10.53.0.4")) + elif lqname == "a.bit.longer.ns.name." and rrtype == AAAA: + r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4")) else: r.authority.append(dns.rrset.from_text(suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) - if bad or not "icky.icky.icky.ptang.zoop.boing.".endswith(lqname): + if bad or not \ + ("icky.icky.icky.ptang.zoop.boing.".endswith(lqname) or \ + "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.".endswith(lqname) or \ + "a.bit.longer.ns.name.".endswith(lqname)): r.set_rcode(NXDOMAIN) if slow: - time.sleep(0.4) + time.sleep(0.2) return r diff --git a/bin/tests/system/qname-minimization/ans3/ans.py b/bin/tests/system/qname-minimization/ans3/ans.py new file mode 100755 index 0000000000..d767403da0 --- /dev/null +++ b/bin/tests/system/qname-minimization/ans3/ans.py @@ -0,0 +1,175 @@ +############################################################################ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. +############################################################################ + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import time +import functools + +import dns, dns.message, dns.query +from dns.rdatatype import * +from dns.rdataclass import * +from dns.rcode import * +from dns.name import * + + +# Log query to file +def logquery(type, qname): + with open("qlog", "a") as f: + f.write("%s %s\n", type, qname) + +############################################################################ +# Respond to a DNS query. +# For good. it serves: +# zoop.boing.good. NS ns3.good. +# icky.ptang.zoop.boing.good. NS a.bit.longer.ns.name.good. +# it responds properly (with NODATA empty response) to non-empty terminals +# +# For slow. it works the same as for good., but each response is delayed by 400 miliseconds +# +# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals +############################################################################ +def create_response(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + lqname = qname.lower() + labels = lqname.split('.') + + # get qtype + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + bad = False + slow = False + + # log this query + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, lqname)) + print("%s %s" % (typename, lqname), end=" ") + + r = dns.message.make_response(m) + r.set_rcode(NOERROR) + + if lqname.endswith("bad."): + bad = True + suffix = "bad." + lqname = lqname[:-4] + elif lqname.endswith("good."): + suffix = "good." + lqname = lqname[:-5] + elif lqname.endswith("slow."): + slow = True + suffix = "slow." + lqname = lqname[:-5] + else: + r.set_rcode(REFUSED) + return r + + # Good/bad differs only in how we treat non-empty terminals + if lqname == "zoop.boing." and rrtype == NS: + r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3."+suffix)) + elif lqname.endswith("icky.ptang.zoop.boing."): + r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix)) + elif "icky.ptang.zoop.boing.".endswith(lqname): + r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + if bad: + r.set_rcode(NXDOMAIN) + elif "zoop.boing.".endswith(lqname): + r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.set_rcode(NXDOMAIN) + else: + r.set_rcode(REFUSED) + + if slow: + time.sleep(0.4) + return r + + +def sigterm(signum, frame): + print ("Shutting down now...") + os.remove('ans.pid') + running = False + sys.exit(0) + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4 = "10.53.0.3" +ip6 = "fd92:7065:b8e:ffff::3" + +try: port=int(os.environ['PORT']) +except: port=5300 + +query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_socket.bind((ip4, port)) + +havev6 = True +try: + query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + try: + query6_socket.bind((ip6, port)) + except: + query6_socket.close() + havev6 = False +except: + havev6 = False + +signal.signal(signal.SIGTERM, sigterm) + +f = open('ans.pid', 'w') +pid = os.getpid() +print (pid, file=f) +f.close() + +running = True + +print ("Listening on %s port %d" % (ip4, port)) +if havev6: + print ("Listening on %s port %d" % (ip6, port)) +print ("Ctrl-c to quit") + +if havev6: + input = [query4_socket, query6_socket] +else: + input = [query4_socket] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == query4_socket or s == query6_socket: + print ("Query received on %s" % + (ip4 if s == query4_socket else ip6), end=" ") + # Handle incoming queries + msg = s.recvfrom(65535) + rsp = create_response(msg[0]) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + else: + print("NO RESPONSE") + if not running: + break diff --git a/bin/tests/system/qname-minimization/ans4/ans.py b/bin/tests/system/qname-minimization/ans4/ans.py new file mode 100755 index 0000000000..aab281a701 --- /dev/null +++ b/bin/tests/system/qname-minimization/ans4/ans.py @@ -0,0 +1,175 @@ +############################################################################ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. +############################################################################ + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import time +import functools + +import dns, dns.message, dns.query +from dns.rdatatype import * +from dns.rdataclass import * +from dns.rcode import * +from dns.name import * + + +# Log query to file +def logquery(type, qname): + with open("qlog", "a") as f: + f.write("%s %s\n", type, qname) + +############################################################################ +# Respond to a DNS query. +# For good. it serves: +# icky.ptang.zoop.boing.good. NS a.bit.longer.ns.name. +# icky.icky.icky.ptang.zoop.boing.good. A 192.0.2.1 +# more.icky.icky.icky.ptang.zoop.boing.good. A 192.0.2.2 +# it responds properly (with NODATA empty response) to non-empty terminals +# +# For slow. it works the same as for good., but each response is delayed by 400 miliseconds +# +# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals +############################################################################ +def create_response(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + lqname = qname.lower() + labels = lqname.split('.') + + # get qtype + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + bad = False + slow = False + + # log this query + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, lqname)) + print("%s %s" % (typename, lqname), end=" ") + + r = dns.message.make_response(m) + r.set_rcode(NOERROR) + + if lqname.endswith("bad."): + bad = True + suffix = "bad." + lqname = lqname[:-4] + elif lqname.endswith("good."): + suffix = "good." + lqname = lqname[:-5] + elif lqname.endswith("slow."): + slow = True + suffix = "slow." + lqname = lqname[:-5] + else: + r.set_rcode(REFUSED) + return r + + # Good/bad differs only in how we treat non-empty terminals + if lqname == "icky.icky.icky.ptang.zoop.boing." and rrtype == A: + r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.1")) + elif lqname == "more.icky.icky.icky.ptang.zoop.boing." and rrtype == A: + r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2")) + elif lqname == "icky.ptang.zoop.boing." and rrtype == NS: + r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name."+suffix)) + elif lqname.endswith("icky.ptang.zoop.boing."): + r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + if bad or not "more.icky.icky.icky.ptang.zoop.boing.".endswith(lqname): + r.set_rcode(NXDOMAIN) + else: + r.set_rcode(REFUSED) + + if slow: + time.sleep(0.4) + return r + + +def sigterm(signum, frame): + print ("Shutting down now...") + os.remove('ans.pid') + running = False + sys.exit(0) + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4 = "10.53.0.4" +ip6 = "fd92:7065:b8e:ffff::4" + +try: port=int(os.environ['PORT']) +except: port=5300 + +query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_socket.bind((ip4, port)) + +havev6 = True +try: + query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + try: + query6_socket.bind((ip6, port)) + except: + query6_socket.close() + havev6 = False +except: + havev6 = False + +signal.signal(signal.SIGTERM, sigterm) + +f = open('ans.pid', 'w') +pid = os.getpid() +print (pid, file=f) +f.close() + +running = True + +print ("Listening on %s port %d" % (ip4, port)) +if havev6: + print ("Listening on %s port %d" % (ip6, port)) +print ("Ctrl-c to quit") + +if havev6: + input = [query4_socket, query6_socket] +else: + input = [query4_socket] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == query4_socket or s == query6_socket: + print ("Query received on %s" % + (ip4 if s == query4_socket else ip6), end=" ") + # Handle incoming queries + msg = s.recvfrom(65535) + rsp = create_response(msg[0]) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + else: + print("NO RESPONSE") + if not running: + break diff --git a/bin/tests/system/qname-minimization/clean.sh b/bin/tests/system/qname-minimization/clean.sh index eaff4210bb..bd5af224a5 100644 --- a/bin/tests/system/qname-minimization/clean.sh +++ b/bin/tests/system/qname-minimization/clean.sh @@ -14,4 +14,4 @@ rm -f */named.memstats rm -f */named.run rm -f dig.out.* rm -f ns*/named.lock -rm -f ans2/query.log +rm -f ans*/query.log diff --git a/bin/tests/system/qname-minimization/ns5/named.conf.in b/bin/tests/system/qname-minimization/ns5/named.conf.in index f570b88835..4d045a58ad 100644 --- a/bin/tests/system/qname-minimization/ns5/named.conf.in +++ b/bin/tests/system/qname-minimization/ns5/named.conf.in @@ -20,8 +20,7 @@ options { listen-on { 10.53.0.5; }; listen-on-v6 { none; }; recursion yes; - qname-minimization yes; - qname-minimization-strict no; + qname-minimization disabled; querylog yes; resolver-query-timeout 30; }; diff --git a/bin/tests/system/qname-minimization/ns3/named.conf.in b/bin/tests/system/qname-minimization/ns6/named.conf.in similarity index 73% rename from bin/tests/system/qname-minimization/ns3/named.conf.in rename to bin/tests/system/qname-minimization/ns6/named.conf.in index 2a6dce9c13..661549b407 100644 --- a/bin/tests/system/qname-minimization/ns3/named.conf.in +++ b/bin/tests/system/qname-minimization/ns6/named.conf.in @@ -9,19 +9,18 @@ * information regarding copyright ownership. */ -// NS3 +// NS6 options { - query-source address 10.53.0.3; - notify-source 10.53.0.3; - transfer-source 10.53.0.3; + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; port @PORT@; pid-file "named.pid"; - listen-on { 10.53.0.3; }; + listen-on { 10.53.0.6; }; listen-on-v6 { none; }; recursion yes; - qname-minimization no; - qname-minimization-strict no; + qname-minimization strict; querylog yes; resolver-query-timeout 30; }; @@ -32,7 +31,7 @@ key rndc_key { }; controls { - inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; }; zone "." { diff --git a/bin/tests/system/qname-minimization/ns4/named.conf.in b/bin/tests/system/qname-minimization/ns7/named.conf.in similarity index 73% rename from bin/tests/system/qname-minimization/ns4/named.conf.in rename to bin/tests/system/qname-minimization/ns7/named.conf.in index 403fc0fd15..48def89b25 100644 --- a/bin/tests/system/qname-minimization/ns4/named.conf.in +++ b/bin/tests/system/qname-minimization/ns7/named.conf.in @@ -9,19 +9,18 @@ * information regarding copyright ownership. */ -// NS4 +// NS7 options { - query-source address 10.53.0.4; - notify-source 10.53.0.4; - transfer-source 10.53.0.4; + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; port @PORT@; pid-file "named.pid"; - listen-on { 10.53.0.4; }; + listen-on { 10.53.0.7; }; listen-on-v6 { none; }; recursion yes; - qname-minimization yes; - qname-minimization-strict yes; + qname-minimization relaxed; querylog yes; resolver-query-timeout 30; }; @@ -32,7 +31,7 @@ key rndc_key { }; controls { - inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; }; zone "." { diff --git a/bin/tests/system/qname-minimization/setup.sh b/bin/tests/system/qname-minimization/setup.sh index 0294ed7487..e9c67c7cb9 100644 --- a/bin/tests/system/qname-minimization/setup.sh +++ b/bin/tests/system/qname-minimization/setup.sh @@ -15,6 +15,6 @@ SYSTEMTESTTOP=.. $SHELL clean.sh copy_setports ns1/named.conf.in ns1/named.conf -copy_setports ns3/named.conf.in ns3/named.conf -copy_setports ns4/named.conf.in ns4/named.conf copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf diff --git a/bin/tests/system/qname-minimization/tests.sh b/bin/tests/system/qname-minimization/tests.sh index 84ab0a4834..bd06cdd123 100755 --- a/bin/tests/system/qname-minimization/tests.sh +++ b/bin/tests/system/qname-minimization/tests.sh @@ -14,7 +14,7 @@ SYSTEMTESTTOP=.. DIGOPTS="-p ${PORT}" RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" -CLEANQL="rm -f ans2/query.log" +CLEANQL="rm -f ans*/query.log" status=0 n=0 @@ -22,10 +22,19 @@ n=`expr $n + 1` echo_i "query for .good is not minimized when qname-minimization is off ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.3 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.3 > dig.out.test$n +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.5 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 -echo "A icky.icky.icky.ptang.zoop.boing.good." | diff ans2/query.log - > /dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +A icky.icky.icky.ptang.zoop.boing.good. +A ns3.good. +AAAA ns3.good. +A a.bit.longer.ns.name.good. +AAAA a.bit.longer.ns.name.good. +__EOF +echo "A icky.icky.icky.ptang.zoop.boing.good." | diff ans3/query.log - > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.good." | diff ans4/query.log - > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -33,10 +42,19 @@ n=`expr $n + 1` echo_i "query for .bad is not minimized when qname-minimization is off ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.3 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.3 > dig.out.test$n +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.5 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 -echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans2/query.log - > /dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +A icky.icky.icky.ptang.zoop.boing.bad. +A ns3.bad. +AAAA ns3.bad. +A a.bit.longer.ns.name.bad. +AAAA a.bit.longer.ns.name.bad. +__EOF +echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans3/query.log - > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans4/query.log - > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -44,10 +62,20 @@ n=`expr $n + 1` echo_i "query for .slow is not minimized when qname-minimization is off ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.3 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.3 > dig.out.test$n +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.5 > dig.out.test$n +sleep 5 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 -echo "A icky.icky.icky.ptang.zoop.boing.slow." | diff ans2/query.log - > /dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.slow. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +A icky.icky.icky.ptang.zoop.boing.slow. +A ns3.slow. +AAAA ns3.slow. +A a.bit.longer.ns.name.slow. +AAAA a.bit.longer.ns.name.slow. +__EOF +echo "A icky.icky.icky.ptang.zoop.boing.slow." | diff ans3/query.log - > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.slow." | diff ans4/query.log - > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -55,14 +83,35 @@ n=`expr $n + 1` echo_i "query for .good is properly minimized when qname-minimization is on ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.4 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.4 > dig.out.test$n +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +# Duplicated NS queries are there because we're not creating +# a separate fetch when doing qname minimization - so two +# queries running for the same name but different RRTYPE +# (A and AAAA in this case) will create separate queries +# for NSes on the way. Those will be cached though, so it +# should not be a problem cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS boing.good. NS zoop.boing.good. +A ns3.good. +AAAA ns3.good. +NS name.good. +NS name.good. +NS ns.name.good. +NS ns.name.good. +NS longer.ns.name.good. +NS longer.ns.name.good. +A a.bit.longer.ns.name.good. +AAAA a.bit.longer.ns.name.good. +__EOF +cat << __EOF | diff ans3/query.log - > /dev/null || ret=1 NS ptang.zoop.boing.good. NS icky.ptang.zoop.boing.good. +__EOF +cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 NS icky.icky.ptang.zoop.boing.good. A icky.icky.icky.ptang.zoop.boing.good. __EOF @@ -70,31 +119,36 @@ if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo_i "query for .bad fails when qname-minimization is on and in strict mode ($n)" +echo_i "query for .bad fails when qname-minimization is in strict mode ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.4 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.4 > dig.out.test$n +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.6 > dig.out.test$n grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 echo "NS boing.bad." | diff ans2/query.log - > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo_i "query for .bad succeds when qname-minimization is on and not in strict mode ($n)" +echo_i "query for .bad succeds when qname-minimization is in relaxed mode ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.5 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.5 > dig.out.test$n +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.7 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS boing.bad. -NS zoop.boing.bad. -NS ptang.zoop.boing.bad. -NS icky.ptang.zoop.boing.bad. -NS icky.icky.ptang.zoop.boing.bad. A icky.icky.icky.ptang.zoop.boing.bad. +A ns3.bad. +AAAA ns3.bad. +NS name.bad. +NS name.bad. +A a.bit.longer.ns.name.bad. +AAAA a.bit.longer.ns.name.bad. __EOF +echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans3/query.log - > /dev/null || ret=1 +echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans4/query.log - > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -102,14 +156,30 @@ n=`expr $n + 1` echo_i "query for .slow is properly minimized when qname-minimization is on ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.4 flush -$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.4 > dig.out.test$n +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.6 > dig.out.test$n +sleep 5 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.slow. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS boing.slow. NS zoop.boing.slow. +A ns3.slow. +AAAA ns3.slow. +NS name.slow. +NS name.slow. +NS ns.name.slow. +NS ns.name.slow. +NS longer.ns.name.slow. +NS longer.ns.name.slow. +A a.bit.longer.ns.name.slow. +AAAA a.bit.longer.ns.name.slow. +__EOF +cat << __EOF | diff ans3/query.log - > /dev/null || ret=1 NS ptang.zoop.boing.slow. NS icky.ptang.zoop.boing.slow. +__EOF +cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 NS icky.icky.ptang.zoop.boing.slow. A icky.icky.icky.ptang.zoop.boing.slow. __EOF @@ -117,12 +187,13 @@ if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo_i "query for .ip6.arpa succeds and skips on boundaries when qname-minimization is on ($n)" +echo_i "query for .ip6.arpa succeds and skips on proper boundaries when qname-minimization is on ($n)" ret=0 $CLEANQL -$RNDCCMD 10.53.0.4 flush -$DIG $DIGOPTS -x 2001:4f8::1 @10.53.0.4 > dig.out.test$n +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS -x 2001:4f8::1 @10.53.0.6 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. 1 IN PTR nee.com." dig.out.test$n > /dev/null || ret=1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS 1.0.0.2.ip6.arpa. NS 8.f.4.0.1.0.0.2.ip6.arpa. @@ -134,5 +205,57 @@ __EOF if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` +n=`expr $n + 1` +echo_i "query for multiple label name skips after 3rd no-delegation response ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. @10.53.0.6 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. 1 IN A 192.0.2.2" dig.out.test$n > /dev/null || ret=1 +# We skipped after third no-delegation. +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +NS z.good. +NS y.z.good. +NS x.y.z.good. +A many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. +__EOF +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "query for multiple label name skips after 7th label ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS more.icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "more.icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.2" dig.out.test$n > /dev/null || ret=1 +cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 +NS boing.good. +NS zoop.boing.good. +A ns3.good. +AAAA ns3.good. +NS name.good. +NS name.good. +NS ns.name.good. +NS ns.name.good. +NS longer.ns.name.good. +NS longer.ns.name.good. +A a.bit.longer.ns.name.good. +AAAA a.bit.longer.ns.name.good. +__EOF +cat << __EOF | diff ans3/query.log - > /dev/null || ret=1 +NS ptang.zoop.boing.good. +NS icky.ptang.zoop.boing.good. +__EOF +# There's no NS icky.icky.ptang.zoop.boing.good. query - we skipped it. +cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 +NS icky.icky.ptang.zoop.boing.good. +A more.icky.icky.icky.ptang.zoop.boing.good. +__EOF +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 044c9a9092..c163053db5 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -4029,6 +4029,14 @@ fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, nameservers = &rdataset; options |= DNS_FETCHOPT_UNSHARED; } + + if (adb->view->qminimization) { + options |= DNS_FETCHOPT_QMINIMIZE; + options |= DNS_FETCHOPT_QMIN_SKIP_ON_IP6A; + if (adb->view->qmin_strict) { + options |= DNS_FETCHOPT_QMIN_STRICT; + } + } fetch = new_adbfetch(adb); if (fetch == NULL) { diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index fbd90a6689..4be589fceb 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -141,6 +141,10 @@ typedef enum { #define DNS_RESOLVER_CHECKNAMES 0x01 #define DNS_RESOLVER_CHECKNAMESFAIL 0x02 +#define DNS_QMIN_MAXLABELS 7 +#define DNS_QMIN_MAX_NO_DELEGATION 3 +#define DNS_MAX_LABELS 127 + isc_result_t dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 1898021672..312d8efa16 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -265,6 +265,7 @@ struct fetchctx { unsigned int dbucketnum; char * info; isc_mem_t * mctx; + isc_stdtime_t now; /*% Locked by appropriate bucket lock. */ fetchstate state; @@ -689,7 +690,7 @@ typedef struct respctx { isc_boolean_t ns_in_answer; /* NS may be in the answer section */ isc_boolean_t negative; /* is this a negative response? */ - isc_stdtime_t now; /* time info */ + isc_stdtime_t now; /* time info */ isc_time_t tnow; isc_time_t *finish; @@ -2542,8 +2543,8 @@ resquery_send(resquery_t *query) { fctx->timeout = ISC_FALSE; /* - * Use EDNS0, unless the caller doesn't want it, or we know that - * the remote server doesn't like it. + * Use EDNS0, unless the caller doesn't want it, or we know that the + * remote server doesn't like it. */ if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) { if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) { @@ -4437,7 +4438,7 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, const isc_sockaddr_t *client, return (ISC_R_NOMEMORY); } event->result = DNS_R_SERVFAIL; - event->qtype = fctx->type; + event->qtype = fctx->fulltype; event->db = NULL; event->node = NULL; event->rdataset = rdataset; @@ -4559,6 +4560,7 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, fctx->minimized = isc_boolean_false; fctx->ip6arpaskip = isc_boolean_false; fctx->qmin_labels = 1; + isc_stdtime_get(&fctx->now); ISC_LIST_INIT(fctx->queries); ISC_LIST_INIT(fctx->finds); ISC_LIST_INIT(fctx->altfinds); @@ -7423,7 +7425,6 @@ rctx_respinit(isc_task_t *task, dns_dispatchevent_t *devent, TIME_NOW(&rctx->tnow); rctx->finish = &rctx->tnow; isc_stdtime_get(&rctx->now); - } /* @@ -8497,7 +8498,20 @@ rctx_answer_none(respctx_t *rctx) { } else { log_formerr(fctx, "invalid response"); } - + /* + * If we're minimizing in relaxed mode, retry with full name, + * just to be safe. The error will be logged. + */ + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, "XXX %d %d", fctx->minimized, fctx->options & DNS_FETCHOPT_QMIN_STRICT); + if (fctx->minimized && + !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, + "disabling qname minimization for '%s'" + " due to formerr", fctx->info); + fctx->qmin_labels = DNS_MAX_LABELS+1; + return rctx_answer_minimized(rctx); + } return (DNS_R_FORMERR); } @@ -8523,12 +8537,17 @@ rctx_answer_none(respctx_t *rctx) { * If we're doing qname minimization this is an empty non-terminal, add * the next label to query and restart it. */ - if (fctx->minimized && - (fctx->rmessage->rcode == dns_rcode_noerror || - !(fctx->options & DNS_FETCHOPT_QMIN_STRICT))) { + if (fctx->minimized && fctx->rmessage->rcode == dns_rcode_noerror) { + return rctx_answer_minimized(rctx); + } + /* + * Workaround for broken servers in relaxed mode - if we hit an + * NXDOMAIN we go straight to the full query. + */ + if (fctx->minimized && !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) { + fctx->qmin_labels = DNS_MAX_LABELS+1; return rctx_answer_minimized(rctx); } - /* * Since we're not doing a referral, we don't want to cache any * NS RRs we may have found. @@ -9079,7 +9098,7 @@ rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo, } result = dns_view_findzonecut(fctx->res->view, name, fname, - rctx->now, findoptions, + fctx->now, findoptions, ISC_TRUE, ISC_TRUE, &fctx->nameservers, NULL); @@ -10283,6 +10302,10 @@ fctx_minimize_qname(fetchctx_t *fctx) { } else if (dlabels + fctx->qmin_labels > 19) { fctx->qmin_labels = 35 - dlabels; } + } else if (dlabels + fctx->qmin_labels > DNS_QMIN_MAXLABELS) { + fctx->qmin_labels = DNS_MAX_LABELS + 1; + } else if (fctx->qmin_labels > DNS_QMIN_MAX_NO_DELEGATION) { + fctx->qmin_labels = DNS_MAX_LABELS + 1; } if (dlabels + fctx->qmin_labels < nlabels) { /* diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 2ac7146794..8c0b68e52a 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -130,6 +130,7 @@ static cfg_type_t cfg_type_optional_uint32; static cfg_type_t cfg_type_options; static cfg_type_t cfg_type_portiplist; static cfg_type_t cfg_type_printtime; +static cfg_type_t cfg_type_qminmethod; static cfg_type_t cfg_type_querysource4; static cfg_type_t cfg_type_querysource6; static cfg_type_t cfg_type_querysource; @@ -1937,8 +1938,7 @@ view_clauses[] = { { "preferred-glue", &cfg_type_astring, 0 }, { "prefetch", &cfg_type_prefetch, 0 }, { "provide-ixfr", &cfg_type_boolean, 0 }, - { "qname-minimization", &cfg_type_boolean, 0 }, - { "qname-minimization-strict", &cfg_type_boolean, 0 }, + { "qname-minimization", &cfg_type_qminmethod, 0 }, /* * Note that the query-source option syntax is different * from the other -source options. @@ -2951,6 +2951,15 @@ static cfg_type_t cfg_type_optional_keyref = { doc_optional_keyvalue, &cfg_rep_string, &key_kw }; +static const char *qminmethod_enums[] = { + "strict", "relaxed", "disabled", NULL +}; + +static cfg_type_t cfg_type_qminmethod = { + "qminmethod", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, qminmethod_enums +}; + #ifdef HAVE_GEOIP /* * "geoip" ACL element: diff --git a/util/copyrights b/util/copyrights index 2e1f6ba4d5..ddeb8eafa2 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1730,12 +1730,14 @@ ./bin/tests/system/pkcs11ssl/tests.sh SH 2014,2016,2018 ./bin/tests/system/pkcs11ssl/usepkcs11 X 2014,2018 ./bin/tests/system/qname-minimization/ans2/ans.py PYTHON 2018 +./bin/tests/system/qname-minimization/ans3/ans.py PYTHON 2018 +./bin/tests/system/qname-minimization/ans4/ans.py PYTHON 2018 ./bin/tests/system/qname-minimization/clean.sh SH 2018 ./bin/tests/system/qname-minimization/ns1/named.conf.in CONF-C 2018 ./bin/tests/system/qname-minimization/ns1/root.db ZONE 2018 -./bin/tests/system/qname-minimization/ns3/named.conf.in CONF-C 2018 -./bin/tests/system/qname-minimization/ns4/named.conf.in CONF-C 2018 ./bin/tests/system/qname-minimization/ns5/named.conf.in CONF-C 2018 +./bin/tests/system/qname-minimization/ns6/named.conf.in CONF-C 2018 +./bin/tests/system/qname-minimization/ns7/named.conf.in CONF-C 2018 ./bin/tests/system/qname-minimization/setup.sh SH 2018 ./bin/tests/system/qname-minimization/tests.sh SH 2018 ./bin/tests/system/reclimit/README TXT.BRIEF 2014,2016,2017,2018 From 4f9c71880350a23311e79a1ef3f4889f4c060049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Fri, 18 May 2018 20:00:31 +0200 Subject: [PATCH 03/15] qname minimization: fix tests --- bin/tests/system/additional/ns2/named.conf.in | 28 +++++++++++++++++++ bin/tests/system/additional/ns2/root.db | 10 +++++++ bin/tests/system/additional/ns3/root.hint | 4 +-- bin/tests/system/additional/setup.sh | 1 + bin/tests/system/reclimit/ns3/named1.conf.in | 1 + bin/tests/system/reclimit/ns3/named2.conf.in | 1 + bin/tests/system/reclimit/ns3/named3.conf.in | 1 + bin/tests/system/reclimit/ns3/named4.conf.in | 1 + bin/tests/system/resolver/ans2/ans.pl | 25 +++++++++++++++-- bin/tests/system/resolver/ans3/ans.pl | 2 ++ bin/tests/system/statistics/ns3/named.conf.in | 1 + util/copyrights | 2 ++ 12 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 bin/tests/system/additional/ns2/named.conf.in create mode 100644 bin/tests/system/additional/ns2/root.db diff --git a/bin/tests/system/additional/ns2/named.conf.in b/bin/tests/system/additional/ns2/named.conf.in new file mode 100644 index 0000000000..1437ec444d --- /dev/null +++ b/bin/tests/system/additional/ns2/named.conf.in @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://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; + recursion no; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + notify no; + minimal-responses yes; +}; + +zone "." { + type master; + file "root.db"; +}; diff --git a/bin/tests/system/additional/ns2/root.db b/bin/tests/system/additional/ns2/root.db new file mode 100644 index 0000000000..c5371e111a --- /dev/null +++ b/bin/tests/system/additional/ns2/root.db @@ -0,0 +1,10 @@ +. IN SOA ns2. hostmaster ( 2 8H 2H 4W 1D); +. NS ns2. +ns1. A 10.53.0.1 +ns2. A 10.53.0.2 +rt.example. NS ns1. +naptr.example. NS ns1. +rt2.example. NS ns1. +naptr2.example. NS ns1. +nid.example. NS ns1. + diff --git a/bin/tests/system/additional/ns3/root.hint b/bin/tests/system/additional/ns3/root.hint index c1784c7ee8..775f78235a 100644 --- a/bin/tests/system/additional/ns3/root.hint +++ b/bin/tests/system/additional/ns3/root.hint @@ -7,5 +7,5 @@ ; See the COPYRIGHT file distributed with this work for additional ; information regarding copyright ownership. -. NS ns1. -ns1. A 10.53.0.1 +. NS ns2. +ns2. A 10.53.0.2 diff --git a/bin/tests/system/additional/setup.sh b/bin/tests/system/additional/setup.sh index 417a8b872f..5f43253079 100644 --- a/bin/tests/system/additional/setup.sh +++ b/bin/tests/system/additional/setup.sh @@ -14,4 +14,5 @@ SYSTEMTESTTOP=.. $SHELL clean.sh copy_setports ns1/named1.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf copy_setports ns3/named.conf.in ns3/named.conf diff --git a/bin/tests/system/reclimit/ns3/named1.conf.in b/bin/tests/system/reclimit/ns3/named1.conf.in index a649db11e3..6275d5904a 100644 --- a/bin/tests/system/reclimit/ns3/named1.conf.in +++ b/bin/tests/system/reclimit/ns3/named1.conf.in @@ -19,6 +19,7 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; servfail-ttl 0; + qname-minimization disabled; max-recursion-depth 12; recursion yes; dnssec-validation yes; diff --git a/bin/tests/system/reclimit/ns3/named2.conf.in b/bin/tests/system/reclimit/ns3/named2.conf.in index 806eb5170e..3d6d27e912 100644 --- a/bin/tests/system/reclimit/ns3/named2.conf.in +++ b/bin/tests/system/reclimit/ns3/named2.conf.in @@ -19,6 +19,7 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; servfail-ttl 0; + qname-minimization disabled; max-recursion-depth 5; recursion yes; dnssec-validation yes; diff --git a/bin/tests/system/reclimit/ns3/named3.conf.in b/bin/tests/system/reclimit/ns3/named3.conf.in index a0c87a2dd9..57dbf032f7 100644 --- a/bin/tests/system/reclimit/ns3/named3.conf.in +++ b/bin/tests/system/reclimit/ns3/named3.conf.in @@ -19,6 +19,7 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; servfail-ttl 0; + qname-minimization disabled; max-recursion-depth 100; max-recursion-queries 50; recursion yes; diff --git a/bin/tests/system/reclimit/ns3/named4.conf.in b/bin/tests/system/reclimit/ns3/named4.conf.in index dd254ad6a1..c095913fe9 100644 --- a/bin/tests/system/reclimit/ns3/named4.conf.in +++ b/bin/tests/system/reclimit/ns3/named4.conf.in @@ -19,6 +19,7 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; servfail-ttl 0; + qname-minimization disabled; max-recursion-depth 100; max-recursion-queries 40; recursion yes; diff --git a/bin/tests/system/resolver/ans2/ans.pl b/bin/tests/system/resolver/ans2/ans.pl index a242a998ec..ee0fed5b25 100644 --- a/bin/tests/system/resolver/ans2/ans.pl +++ b/bin/tests/system/resolver/ans2/ans.pl @@ -57,7 +57,13 @@ for (;;) { my $qname = $questions[0]->qname; my $qtype = $questions[0]->qtype; - if ($qname eq "cname1.example.com") { + if ($qname eq "com" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("com 300 NS a.root-servers.nil.")); + } elsif ($qname eq "example.com" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.com 300 NS a.root-servers.nil.")); + } elsif ($qname eq "cname1.example.com") { # Data for the "cname + other data / 1" test $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 CNAME cname1.example.com")); $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 A 1.2.3.4")); @@ -65,6 +71,15 @@ for (;;) { # Data for the "cname + other data / 2" test: same RRs in opposite order $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 A 1.2.3.4")); $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 CNAME cname2.example.com")); + } elsif ($qname eq "org" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("org 300 NS a.root-servers.nil.")); + } elsif ($qname eq "example.org" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.org 300 NS a.root-servers.nil.")); + } elsif (($qname eq "baddname.example.org" || $qname eq "gooddname.example.org") && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.org 300 NS a.root-servers.nil.")); } elsif ($qname eq "www.example.org" || $qname eq "www.example.net" || $qname eq "badcname.example.org" || $qname eq "goodcname.example.org" || @@ -81,6 +96,12 @@ for (;;) { new Net::DNS::RR($qname . " 300 AAAA 2001:db8:beef::1")); } + } elsif ($qname eq "net" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("net 300 NS a.root-servers.nil.")); + } elsif ($qname eq "example.net" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.net 300 NS a.root-servers.nil.")); } elsif ($qname eq "badcname.example.net" || $qname eq "goodcname.example.net") { # Data for CNAME/DNAME filtering. We need to make one-level @@ -97,7 +118,7 @@ for (;;) { # expected to be accepted regardless of the filter setting. $packet->push("authority", new Net::DNS::RR("sub.example.org 300 NS ns.sub.example.org")); $packet->push("additional", new Net::DNS::RR("ns.sub.example.org 300 A 10.53.0.3")); - } elsif ($qname =~ /\.broken/) { + } elsif ($qname =~ /broken/) { # Delegation to broken TLD. $packet->push("authority", new Net::DNS::RR("broken 300 NS ns.broken")); $packet->push("additional", new Net::DNS::RR("ns.broken 300 A 10.53.0.4")); diff --git a/bin/tests/system/resolver/ans3/ans.pl b/bin/tests/system/resolver/ans3/ans.pl index 46d767378d..4f1ef38bf5 100644 --- a/bin/tests/system/resolver/ans3/ans.pl +++ b/bin/tests/system/resolver/ans3/ans.pl @@ -61,6 +61,8 @@ for (;;) { $packet->push("answer", new Net::DNS::RR($qname . " 300 CNAME badcname.example.org")); + } elsif (($qname eq "baddname.example.net" || $qname eq "gooddname.example.net") && $qtype eq "NS") { + $packet->push("authority", new Net::DNS::RR("example.net IN SOA (1 2 3 4 5)")) } elsif ($qname eq "foo.baddname.example.net") { $packet->push("answer", new Net::DNS::RR("baddname.example.net" . diff --git a/bin/tests/system/statistics/ns3/named.conf.in b/bin/tests/system/statistics/ns3/named.conf.in index 67d041b67a..c3c9208870 100644 --- a/bin/tests/system/statistics/ns3/named.conf.in +++ b/bin/tests/system/statistics/ns3/named.conf.in @@ -21,6 +21,7 @@ options { recursion yes; dnssec-validation yes; notify yes; + qname-minimization disabled; }; statistics-channels { diff --git a/util/copyrights b/util/copyrights index ddeb8eafa2..22dbf69854 100644 --- a/util/copyrights +++ b/util/copyrights @@ -433,6 +433,8 @@ ./bin/tests/system/additional/ns1/rt.db ZONE 2013,2016,2018 ./bin/tests/system/additional/ns1/rt2.db ZONE 2013,2016,2018 ./bin/tests/system/additional/ns1/srv.db ZONE 2016,2018 +./bin/tests/system/additional/ns2/named.conf.in CONF-C 2018 +./bin/tests/system/additional/ns2/root.db ZONE 2018 ./bin/tests/system/additional/ns3/named.conf.in CONF-C 2017,2018 ./bin/tests/system/additional/ns3/root.hint ZONE 2017,2018 ./bin/tests/system/additional/setup.sh SH 2013,2016,2018 From 2ea47c7f34bf2d2971ed2c5fa1651af43c5a3117 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Fri, 18 May 2018 13:07:31 -0700 Subject: [PATCH 04/15] rename test to qmin; add it to conf.sh.in and Makefile.in; fix copyrights --- bin/tests/system/Makefile.in | 2 +- bin/tests/system/additional/ns2/root.db | 9 ++++++++ bin/tests/system/conf.sh.in | 2 +- bin/tests/system/conf.sh.win32 | 4 ++-- .../{qname-minimization => qmin}/ans2/ans.py | 0 .../{qname-minimization => qmin}/ans3/ans.py | 2 +- .../{qname-minimization => qmin}/ans4/ans.py | 0 .../{qname-minimization => qmin}/clean.sh | 0 .../ns1/named.conf.in | 0 .../{qname-minimization => qmin}/ns1/root.db | 0 .../ns5/named.conf.in | 0 .../ns6/named.conf.in | 0 .../ns7/named.conf.in | 0 .../{qname-minimization => qmin}/setup.sh | 0 .../{qname-minimization => qmin}/tests.sh | 2 +- lib/dns/adb.c | 2 +- lib/dns/resolver.c | 4 ++-- util/copyrights | 22 +++++++++---------- 18 files changed, 29 insertions(+), 20 deletions(-) rename bin/tests/system/{qname-minimization => qmin}/ans2/ans.py (100%) rename bin/tests/system/{qname-minimization => qmin}/ans3/ans.py (99%) rename bin/tests/system/{qname-minimization => qmin}/ans4/ans.py (100%) rename bin/tests/system/{qname-minimization => qmin}/clean.sh (100%) rename bin/tests/system/{qname-minimization => qmin}/ns1/named.conf.in (100%) rename bin/tests/system/{qname-minimization => qmin}/ns1/root.db (100%) rename bin/tests/system/{qname-minimization => qmin}/ns5/named.conf.in (100%) rename bin/tests/system/{qname-minimization => qmin}/ns6/named.conf.in (100%) rename bin/tests/system/{qname-minimization => qmin}/ns7/named.conf.in (100%) rename bin/tests/system/{qname-minimization => qmin}/setup.sh (100%) rename bin/tests/system/{qname-minimization => qmin}/tests.sh (99%) diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in index a552f4667e..c17fac83d2 100644 --- a/bin/tests/system/Makefile.in +++ b/bin/tests/system/Makefile.in @@ -64,7 +64,7 @@ PARALLEL = rpzrecurse serve-stale dnssec \ legacy limits logfileconfig \ masterfile masterformat metadata mkeys \ names notify nslookup nsupdate nzd2nzf \ - padding pending pipelined \ + padding pending pipelined qmin \ reclimit redirect resolver rndc rootkeysentinel rpz \ rrchecker rrl rrsetorder rsabigexponent runtime \ sfcache smartsign sortlist \ diff --git a/bin/tests/system/additional/ns2/root.db b/bin/tests/system/additional/ns2/root.db index c5371e111a..3241240784 100644 --- a/bin/tests/system/additional/ns2/root.db +++ b/bin/tests/system/additional/ns2/root.db @@ -1,3 +1,12 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; 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 http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + . IN SOA ns2. hostmaster ( 2 8H 2H 4W 1D); . NS ns2. ns1. A 10.53.0.1 diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index e4d60eaa18..1e4f97d106 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -95,7 +95,7 @@ PARALLELDIRS="acl additional addzone allow-query auth autosign \ legacy limits logfileconfig \ masterfile masterformat metadata mkeys \ names notify nslookup nsupdate nzd2nzf \ - padding pending pipelined \ + padding pending pipelined qmin \ reclimit redirect resolver rndc rootkeysentinel rpz rpzrecurse \ rrchecker rrl rrsetorder rsabigexponent runtime \ serve-stale sfcache smartsign sortlist \ diff --git a/bin/tests/system/conf.sh.win32 b/bin/tests/system/conf.sh.win32 index 6bfac1357c..b178179909 100644 --- a/bin/tests/system/conf.sh.win32 +++ b/bin/tests/system/conf.sh.win32 @@ -91,8 +91,8 @@ SEQUENTIALDIRS="acl additional addzone autosign builtin \ fetchlimit filter-aaaa formerr forward geoip glue idna inline ixfr \ keepalive @KEYMGR@ legacy limits logfileconfig masterfile \ masterformat metadata mkeys names notify nslookup nsupdate \ - nzd2nzf padding pending pipelined @PKCS11_TEST@ reclimit \ - redirect resolver rndc rpz rrchecker rrl \ + nzd2nzf padding pending pipelined @PKCS11_TEST@ qmin + reclimit redirect resolver rndc rpz rrchecker rrl \ rrsetorder rsabigexponent runtime sfcache smartsign sortlist \ spf staticstub statistics statschannel stub tcp tkey tsig \ tsiggss unknown upforwd verify views wildcard xfer xferquota \ diff --git a/bin/tests/system/qname-minimization/ans2/ans.py b/bin/tests/system/qmin/ans2/ans.py similarity index 100% rename from bin/tests/system/qname-minimization/ans2/ans.py rename to bin/tests/system/qmin/ans2/ans.py diff --git a/bin/tests/system/qname-minimization/ans3/ans.py b/bin/tests/system/qmin/ans3/ans.py similarity index 99% rename from bin/tests/system/qname-minimization/ans3/ans.py rename to bin/tests/system/qmin/ans3/ans.py index d767403da0..1a0d82e5ce 100755 --- a/bin/tests/system/qname-minimization/ans3/ans.py +++ b/bin/tests/system/qmin/ans3/ans.py @@ -34,7 +34,7 @@ def logquery(type, qname): ############################################################################ # Respond to a DNS query. # For good. it serves: -# zoop.boing.good. NS ns3.good. +# zoop.boing.good. NS ns3.good. # icky.ptang.zoop.boing.good. NS a.bit.longer.ns.name.good. # it responds properly (with NODATA empty response) to non-empty terminals # diff --git a/bin/tests/system/qname-minimization/ans4/ans.py b/bin/tests/system/qmin/ans4/ans.py similarity index 100% rename from bin/tests/system/qname-minimization/ans4/ans.py rename to bin/tests/system/qmin/ans4/ans.py diff --git a/bin/tests/system/qname-minimization/clean.sh b/bin/tests/system/qmin/clean.sh similarity index 100% rename from bin/tests/system/qname-minimization/clean.sh rename to bin/tests/system/qmin/clean.sh diff --git a/bin/tests/system/qname-minimization/ns1/named.conf.in b/bin/tests/system/qmin/ns1/named.conf.in similarity index 100% rename from bin/tests/system/qname-minimization/ns1/named.conf.in rename to bin/tests/system/qmin/ns1/named.conf.in diff --git a/bin/tests/system/qname-minimization/ns1/root.db b/bin/tests/system/qmin/ns1/root.db similarity index 100% rename from bin/tests/system/qname-minimization/ns1/root.db rename to bin/tests/system/qmin/ns1/root.db diff --git a/bin/tests/system/qname-minimization/ns5/named.conf.in b/bin/tests/system/qmin/ns5/named.conf.in similarity index 100% rename from bin/tests/system/qname-minimization/ns5/named.conf.in rename to bin/tests/system/qmin/ns5/named.conf.in diff --git a/bin/tests/system/qname-minimization/ns6/named.conf.in b/bin/tests/system/qmin/ns6/named.conf.in similarity index 100% rename from bin/tests/system/qname-minimization/ns6/named.conf.in rename to bin/tests/system/qmin/ns6/named.conf.in diff --git a/bin/tests/system/qname-minimization/ns7/named.conf.in b/bin/tests/system/qmin/ns7/named.conf.in similarity index 100% rename from bin/tests/system/qname-minimization/ns7/named.conf.in rename to bin/tests/system/qmin/ns7/named.conf.in diff --git a/bin/tests/system/qname-minimization/setup.sh b/bin/tests/system/qmin/setup.sh similarity index 100% rename from bin/tests/system/qname-minimization/setup.sh rename to bin/tests/system/qmin/setup.sh diff --git a/bin/tests/system/qname-minimization/tests.sh b/bin/tests/system/qmin/tests.sh similarity index 99% rename from bin/tests/system/qname-minimization/tests.sh rename to bin/tests/system/qmin/tests.sh index bd06cdd123..edd76942ae 100755 --- a/bin/tests/system/qname-minimization/tests.sh +++ b/bin/tests/system/qmin/tests.sh @@ -89,7 +89,7 @@ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 # Duplicated NS queries are there because we're not creating # a separate fetch when doing qname minimization - so two -# queries running for the same name but different RRTYPE +# queries running for the same name but different RRTYPE # (A and AAAA in this case) will create separate queries # for NSes on the way. Those will be cached though, so it # should not be a problem diff --git a/lib/dns/adb.c b/lib/dns/adb.c index c163053db5..adcf733b51 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -4029,7 +4029,7 @@ fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, nameservers = &rdataset; options |= DNS_FETCHOPT_UNSHARED; } - + if (adb->view->qminimization) { options |= DNS_FETCHOPT_QMINIMIZE; options |= DNS_FETCHOPT_QMIN_SKIP_ON_IP6A; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 312d8efa16..e1c1753498 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -8509,7 +8509,7 @@ rctx_answer_none(respctx_t *rctx) { DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, "disabling qname minimization for '%s'" " due to formerr", fctx->info); - fctx->qmin_labels = DNS_MAX_LABELS+1; + fctx->qmin_labels = DNS_MAX_LABELS+1; return rctx_answer_minimized(rctx); } return (DNS_R_FORMERR); @@ -8545,7 +8545,7 @@ rctx_answer_none(respctx_t *rctx) { * NXDOMAIN we go straight to the full query. */ if (fctx->minimized && !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) { - fctx->qmin_labels = DNS_MAX_LABELS+1; + fctx->qmin_labels = DNS_MAX_LABELS+1; return rctx_answer_minimized(rctx); } /* diff --git a/util/copyrights b/util/copyrights index 22dbf69854..84bfd1ed00 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1731,17 +1731,17 @@ ./bin/tests/system/pkcs11ssl/setup.sh SH 2014,2016,2018 ./bin/tests/system/pkcs11ssl/tests.sh SH 2014,2016,2018 ./bin/tests/system/pkcs11ssl/usepkcs11 X 2014,2018 -./bin/tests/system/qname-minimization/ans2/ans.py PYTHON 2018 -./bin/tests/system/qname-minimization/ans3/ans.py PYTHON 2018 -./bin/tests/system/qname-minimization/ans4/ans.py PYTHON 2018 -./bin/tests/system/qname-minimization/clean.sh SH 2018 -./bin/tests/system/qname-minimization/ns1/named.conf.in CONF-C 2018 -./bin/tests/system/qname-minimization/ns1/root.db ZONE 2018 -./bin/tests/system/qname-minimization/ns5/named.conf.in CONF-C 2018 -./bin/tests/system/qname-minimization/ns6/named.conf.in CONF-C 2018 -./bin/tests/system/qname-minimization/ns7/named.conf.in CONF-C 2018 -./bin/tests/system/qname-minimization/setup.sh SH 2018 -./bin/tests/system/qname-minimization/tests.sh SH 2018 +./bin/tests/system/qmin/ans2/ans.py PYTHON 2018 +./bin/tests/system/qmin/ans3/ans.py PYTHON 2018 +./bin/tests/system/qmin/ans4/ans.py PYTHON 2018 +./bin/tests/system/qmin/clean.sh SH 2018 +./bin/tests/system/qmin/ns1/named.conf.in CONF-C 2018 +./bin/tests/system/qmin/ns1/root.db ZONE 2018 +./bin/tests/system/qmin/ns5/named.conf.in CONF-C 2018 +./bin/tests/system/qmin/ns6/named.conf.in CONF-C 2018 +./bin/tests/system/qmin/ns7/named.conf.in CONF-C 2018 +./bin/tests/system/qmin/setup.sh SH 2018 +./bin/tests/system/qmin/tests.sh SH 2018 ./bin/tests/system/reclimit/README TXT.BRIEF 2014,2016,2017,2018 ./bin/tests/system/reclimit/ans2/ans.pl PERL 2014,2015,2016,2017,2018 ./bin/tests/system/reclimit/ans7/ans.pl PERL 2014,2016,2018 From c8015eb33b1f30cef08158eacc7174038de5b215 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Fri, 18 May 2018 13:35:03 -0700 Subject: [PATCH 05/15] style nits (mostly line length) --- lib/dns/adb.c | 2 +- lib/dns/include/dns/resolver.h | 13 ++++++---- lib/dns/resolver.c | 47 ++++++++++++++++++++++------------ lib/ns/query.c | 5 ++-- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/lib/dns/adb.c b/lib/dns/adb.c index adcf733b51..e7d3e3ee7d 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -4032,7 +4032,7 @@ fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, if (adb->view->qminimization) { options |= DNS_FETCHOPT_QMINIMIZE; - options |= DNS_FETCHOPT_QMIN_SKIP_ON_IP6A; + options |= DNS_FETCHOPT_QMIN_SKIP_IP6A; if (adb->view->qmin_strict) { options |= DNS_FETCHOPT_QMIN_STRICT; } diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 4be589fceb..daec139fbe 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -105,12 +105,15 @@ typedef enum { /* RESERVED ECS 0x2000 */ /* RESERVED TCPCLIENT 0x4000 */ #define DNS_FETCHOPT_NOCACHED 0x8000 /*%< Force cache update. */ -#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname minimization. */ -#define DNS_FETCHOPT_QMIN_STRICT 0x00020000 /*%< Do not work around servers that - return errors on non-empty +#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname + minimization. */ +#define DNS_FETCHOPT_QMIN_STRICT 0x00020000 /*%< Do not work around + servers that return + errors on non-empty terminals. */ -#define DNS_FETCHOPT_QMIN_SKIP_ON_IP6A 0x00040000 /*%< Skip some labels when - doing qname minimization on +#define DNS_FETCHOPT_QMIN_SKIP_IP6A 0x00040000 /*%< Skip some labels + when doing qname + minimization on ip6.arpa. */ /* Reserved in use by adb.c 0x00400000 */ diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index e1c1753498..f8b8e39505 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2973,7 +2973,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { FCTXTRACE("query canceled: " "resquery_send() failed; responding"); - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, + ISC_FALSE, ISC_FALSE); fctx_done(fctx, result, __LINE__); } break; @@ -2992,7 +2993,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { * No route to remote. */ isc_socket_detach(&query->tcpsocket); - fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, + ISC_TRUE, ISC_FALSE); retry = ISC_TRUE; break; @@ -3002,7 +3004,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { sevent->result); isc_socket_detach(&query->tcpsocket); - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, + ISC_FALSE, ISC_FALSE); break; } } @@ -4759,8 +4762,10 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, * If qname minimization is enabled we need to trim * the name in fctx to proper length. */ - if (options & DNS_FETCHOPT_QMINIMIZE) { - fctx->ip6arpaskip = (options & DNS_FETCHOPT_QMIN_SKIP_ON_IP6A) && dns_name_issubdomain(&fctx->name, &ip6_arpa); + if ((options & DNS_FETCHOPT_QMINIMIZE) != 0) { + fctx->ip6arpaskip = + ISC_TF((options & DNS_FETCHOPT_QMIN_SKIP_IP6A) != 0 && + dns_name_issubdomain(&fctx->name, &ip6_arpa)); fctx_minimize_qname(fctx); } @@ -8502,15 +8507,18 @@ rctx_answer_none(respctx_t *rctx) { * If we're minimizing in relaxed mode, retry with full name, * just to be safe. The error will be logged. */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, "XXX %d %d", fctx->minimized, fctx->options & DNS_FETCHOPT_QMIN_STRICT); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, + "XXX %d %d", fctx->minimized, + fctx->options & DNS_FETCHOPT_QMIN_STRICT); if (fctx->minimized && - !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) { + (fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, - "disabling qname minimization for '%s'" - " due to formerr", fctx->info); - fctx->qmin_labels = DNS_MAX_LABELS+1; - return rctx_answer_minimized(rctx); + "disabling qname minimization for '%s' " + "due to formerr", fctx->info); + fctx->qmin_labels = DNS_MAX_LABELS + 1; + return (rctx_answer_minimized(rctx)); } return (DNS_R_FORMERR); } @@ -10274,7 +10282,10 @@ log_fetch(const dns_name_t *name, dns_rdatatype_t type) { void fctx_minimize_qname(fetchctx_t *fctx) { - /* XXXWPK TODO we should update info to show that this query is minimized */ + /* + * XXXWPK TODO we should update info to show that this query + * is minimized + */ unsigned int dlabels, nlabels; dlabels = dns_name_countlabels(&fctx->domain); @@ -10283,9 +10294,9 @@ fctx_minimize_qname(fetchctx_t *fctx) { dns_name_init(&fctx->name, NULL); if (fctx->ip6arpaskip) { /* - * For ip6.arpa we want to skip some of the labels, with boundaries - * at /16, /32, /48, /56, /64 and /128 - * in 'label count' terms that's equal to + * For ip6.arpa we want to skip some of the labels, with + * boundaries at /16, /32, /48, /56, /64 and /128 + * In 'label count' terms that's equal to * 7 11 15 17 19 35 * We fix fctx->qmin_labels to point to the nearest boundary */ @@ -10309,14 +10320,16 @@ fctx_minimize_qname(fetchctx_t *fctx) { } if (dlabels + fctx->qmin_labels < nlabels) { /* - * We want to query for [qmin_labels from fctx->fullname] + fctx->domain + * We want to query for + * [qmin_labels from fctx->fullname] + fctx->domain */ dns_fixedname_t fname; dns_fixedname_init(&fname); dns_name_split(&fctx->fullname, dlabels + fctx->qmin_labels, NULL, dns_fixedname_name(&fname)); - dns_name_dup(dns_fixedname_name(&fname), fctx->mctx, &fctx->name); + dns_name_dup(dns_fixedname_name(&fname), fctx->mctx, + &fctx->name); fctx->type = dns_rdatatype_ns; fctx->minimized = isc_boolean_true; } else { diff --git a/lib/ns/query.c b/lib/ns/query.c index 037bc0653d..c31f398592 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -11108,10 +11108,9 @@ ns_query_start(ns_client_t *client) { if (client->view->qminimization) { client->query.fetchoptions |= DNS_FETCHOPT_QMINIMIZE | - DNS_FETCHOPT_QMIN_SKIP_ON_IP6A; + DNS_FETCHOPT_QMIN_SKIP_IP6A; if (client->view->qmin_strict) { - client->query.fetchoptions |= - DNS_FETCHOPT_QMIN_STRICT; + client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT; } } From c04784c144850a7deb4a510b2df78e5a5a1de4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Tue, 22 May 2018 09:58:24 +0200 Subject: [PATCH 06/15] Disable qname minimization if we encounter a bad server --- lib/dns/resolver.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index f8b8e39505..d311ff33e1 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -65,7 +65,7 @@ #include #include #include - +#define WANT_QUERYTRACE #ifdef WANT_QUERYTRACE #define RTRACE(m) isc_log_write(dns_lctx, \ DNS_LOGCATEGORY_RESOLVER, \ @@ -8507,10 +8507,6 @@ rctx_answer_none(respctx_t *rctx) { * If we're minimizing in relaxed mode, retry with full name, * just to be safe. The error will be logged. */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, - DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, - "XXX %d %d", fctx->minimized, - fctx->options & DNS_FETCHOPT_QMIN_STRICT); if (fctx->minimized && (fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, @@ -8553,7 +8549,7 @@ rctx_answer_none(respctx_t *rctx) { * NXDOMAIN we go straight to the full query. */ if (fctx->minimized && !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) { - fctx->qmin_labels = DNS_MAX_LABELS+1; + fctx->qmin_labels = DNS_MAX_LABELS + 1; return rctx_answer_minimized(rctx); } /* @@ -9398,15 +9394,27 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) { } /* - * Some servers do not ignore unknown EDNS options. + * If we're minimizing in relaxed mode try to disable minimization. */ - if (!NOCOOKIE(query->addrinfo) && + if (fctx->minimized && + (fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) + { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, + "disabling qname minimization for '%s'" + " due to bad server", fctx->info); + fctx->qmin_labels = DNS_MAX_LABELS + 1; + result = rctx_answer_minimized(rctx); + } else if (!NOCOOKIE(query->addrinfo) && (fctx->rmessage->rcode == dns_rcode_formerr || fctx->rmessage->rcode == dns_rcode_notimp || fctx->rmessage->rcode == dns_rcode_refused) && dns_adb_getcookie(fctx->adb, query->addrinfo, cookie, sizeof(cookie)) == 0U) { + /* + * Some servers do not ignore unknown EDNS options. + */ dns_adb_changeflags(fctx->adb, query->addrinfo, FCTX_ADDRINFO_NOCOOKIE, FCTX_ADDRINFO_NOCOOKIE); From 058ce1e732c8c155691e3d0ae3bb386106099e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Tue, 22 May 2018 10:22:24 +0200 Subject: [PATCH 07/15] qname minimization: log how many qmin steps were taken --- lib/dns/resolver.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index d311ff33e1..5294807771 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -65,7 +65,7 @@ #include #include #include -#define WANT_QUERYTRACE + #ifdef WANT_QUERYTRACE #define RTRACE(m) isc_log_write(dns_lctx, \ DNS_LOGCATEGORY_RESOLVER, \ @@ -308,6 +308,7 @@ struct fetchctx { isc_counter_t * qc; isc_boolean_t minimized; unsigned int qmin_labels; + unsigned int qmin_steps; isc_boolean_t ip6arpaskip; dns_name_t name; dns_rdatatype_t type; @@ -4563,6 +4564,7 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, fctx->minimized = isc_boolean_false; fctx->ip6arpaskip = isc_boolean_false; fctx->qmin_labels = 1; + fctx->qmin_steps = 0; isc_stdtime_get(&fctx->now); ISC_LIST_INIT(fctx->queries); ISC_LIST_INIT(fctx->finds); @@ -10340,6 +10342,7 @@ fctx_minimize_qname(fetchctx_t *fctx) { &fctx->name); fctx->type = dns_rdatatype_ns; fctx->minimized = isc_boolean_true; + fctx->qmin_steps++; } else { /* Minimization is done, we'll ask for whole qname */ fctx->type = fctx->fulltype; @@ -10612,7 +10615,8 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx, "%06" ISC_PRINT_QUADFORMAT "u: %s/%s " "[domain:%s,referral:%u,restart:%u,qrysent:%u," "timeout:%u,lame:%u,quota:%u,neterr:%u," - "badresp:%u,adberr:%u,findfail:%u,valfail:%u]", + "badresp:%u,adberr:%u,findfail:%u,valfail:%u," + "qminsteps:%u]", __FILE__, fctx->exitline, fctx->info, fctx->duration / US_PER_SEC, fctx->duration % US_PER_SEC, @@ -10622,7 +10626,8 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx, fctx->querysent, fctx->timeouts, fctx->lamecount, fctx->quotacount, fctx->neterr, fctx->badresp, fctx->adberr, - fctx->findfail, fctx->valfail); + fctx->findfail, fctx->valfail, + fctx->qmin_steps); fctx->logged = ISC_TRUE; } From 31b0dc1f204d8f7520145f21e8ea46d1466412a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Fri, 25 May 2018 14:24:21 +0200 Subject: [PATCH 08/15] Require python with dnspython module --- configure | 30 +++++++++++++++++++++++++++++- configure.in | 13 +++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 304065bd16..4e2ef04084 100755 --- a/configure +++ b/configure @@ -936,6 +936,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -1094,6 +1095,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1346,6 +1348,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1483,7 +1494,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1636,6 +1647,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -12208,6 +12220,9 @@ except: exit(1)' testply='try: from ply import * except: exit(1)' +testdnspython='try: import dns.message +except: exit(1)' + testminvers='import sys if (sys.version_info < (2,7)) or (sys.version_info < (3,2) and sys.version_info >= (3,0)): exit(1)' @@ -12301,6 +12316,19 @@ $as_echo "not found" >&6; } $as_echo_n "checking python module 'ply'... " >&6; } if ${PYTHON:-false} -c "$testply"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + unset ac_cv_path_PYTHON + unset PYTHON + continue + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking python module 'dnspython'" >&5 +$as_echo_n "checking python module 'dnspython'... " >&6; } + if ${PYTHON:-false} -c "$testdnspython"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 $as_echo "found" >&6; } break else diff --git a/configure.in b/configure.in index 15db7a1e32..23c7a3124c 100644 --- a/configure.in +++ b/configure.in @@ -185,6 +185,9 @@ except: exit(1)' testply='try: from ply import * except: exit(1)' +testdnspython='try: import dns.message +except: exit(1)' + testminvers='import sys if (sys.version_info < (2,7)) or (sys.version_info < (3,2) and sys.version_info >= (3,0)): exit(1)' @@ -225,6 +228,16 @@ case "$use_python" in AC_MSG_CHECKING([python module 'ply']) if ${PYTHON:-false} -c "$testply"; then AC_MSG_RESULT([found]) + else + AC_MSG_RESULT([not found]) + unset ac_cv_path_PYTHON + unset PYTHON + continue + fi + + AC_MSG_CHECKING([python module 'dnspython']) + if ${PYTHON:-false} -c "$testdnspython"; then + AC_MSG_RESULT([found]) break else AC_MSG_RESULT([not found]) From 1bf6b3ea6516cf5cae0621b7aea9396ff85c0aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Fri, 25 May 2018 16:41:59 +0200 Subject: [PATCH 09/15] +x permissions on bin/tests/system scripts --- bin/tests/system/ifconfig.sh | 0 bin/tests/system/run.sh | 0 bin/tests/system/runall.sh | 0 bin/tests/system/runsequential.sh | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/tests/system/ifconfig.sh mode change 100644 => 100755 bin/tests/system/run.sh mode change 100644 => 100755 bin/tests/system/runall.sh mode change 100644 => 100755 bin/tests/system/runsequential.sh diff --git a/bin/tests/system/ifconfig.sh b/bin/tests/system/ifconfig.sh old mode 100644 new mode 100755 diff --git a/bin/tests/system/run.sh b/bin/tests/system/run.sh old mode 100644 new mode 100755 diff --git a/bin/tests/system/runall.sh b/bin/tests/system/runall.sh old mode 100644 new mode 100755 diff --git a/bin/tests/system/runsequential.sh b/bin/tests/system/runsequential.sh old mode 100644 new mode 100755 From 9cef87d83531feefa8c8b5d09b15f016a04076f8 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 29 May 2018 17:44:16 +1000 Subject: [PATCH 10/15] update qname-minimization --- doc/misc/options | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/misc/options b/doc/misc/options index 51e97d563e..60ddaea3b2 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -264,8 +264,7 @@ options { preferred-glue ; prefetch [ ]; provide-ixfr ; - qname-minimization ; - qname-minimization-strict ; + qname-minimization ( strict | relaxed | disabled ); query-source ( ( [ address ] ( | * ) [ port ( | * ) ] ) | ( [ [ address ] ( | * ) ] port ( | * ) ) ) [ dscp ]; From 265052df4932aeb5b9f4d6c5c2ca2c7279794588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Tue, 29 May 2018 10:22:34 +0200 Subject: [PATCH 11/15] qname-minimization: Some post-review style/minor fixes --- bin/named/config.c | 2 +- bin/named/server.c | 3 +- bin/tests/system/conf.sh.win32 | 4 +- bin/tests/system/qmin/clean.sh | 1 + bin/tests/system/qmin/tests.sh | 9 +++++ bin/tests/system/resolver/ans2/ans.pl | 2 +- doc/arm/notes.xml | 9 +++++ lib/dns/include/dns/resolver.h | 54 +++++++++++++-------------- lib/dns/resolver.c | 9 +++-- 9 files changed, 57 insertions(+), 36 deletions(-) diff --git a/bin/named/config.c b/bin/named/config.c index 3e4ceaea53..14b3228750 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -183,9 +183,9 @@ options {\n\ notify-source-v6 *;\n\ nsec3-test-zone no;\n\ provide-ixfr true;\n\ + qname-minimization relaxed;\n\ query-source address *;\n\ query-source-v6 address *;\n\ - qname-minimization relaxed;\n\ recursion true;\n\ request-expire true;\n\ request-ixfr true;\n\ diff --git a/bin/named/server.c b/bin/named/server.c index 38f9df1a0f..bfdc2af9b7 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -3690,6 +3690,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, isc_dscp_t dscp4 = -1, dscp6 = -1; dns_dyndbctx_t *dctx = NULL; unsigned int resolver_param; + const char * qminmode = NULL; REQUIRE(DNS_VIEW_VALID(view)); @@ -4642,7 +4643,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, obj = NULL; result = named_config_get(maps, "qname-minimization", &obj); INSIST(result == ISC_R_SUCCESS); - const char * qminmode = cfg_obj_asstring(obj); + qminmode = cfg_obj_asstring(obj); INSIST(qminmode != NULL); if (!strcmp(qminmode, "strict")) { view->qminimization = ISC_TRUE; diff --git a/bin/tests/system/conf.sh.win32 b/bin/tests/system/conf.sh.win32 index b178179909..1e9c02d697 100644 --- a/bin/tests/system/conf.sh.win32 +++ b/bin/tests/system/conf.sh.win32 @@ -91,8 +91,8 @@ SEQUENTIALDIRS="acl additional addzone autosign builtin \ fetchlimit filter-aaaa formerr forward geoip glue idna inline ixfr \ keepalive @KEYMGR@ legacy limits logfileconfig masterfile \ masterformat metadata mkeys names notify nslookup nsupdate \ - nzd2nzf padding pending pipelined @PKCS11_TEST@ qmin - reclimit redirect resolver rndc rpz rrchecker rrl \ + nzd2nzf padding pending pipelined @PKCS11_TEST@ qmin \ + reclimit redirect resolver rndc rpz rrchecker rrl \ rrsetorder rsabigexponent runtime sfcache smartsign sortlist \ spf staticstub statistics statschannel stub tcp tkey tsig \ tsiggss unknown upforwd verify views wildcard xfer xferquota \ diff --git a/bin/tests/system/qmin/clean.sh b/bin/tests/system/qmin/clean.sh index bd5af224a5..55a4fa8d35 100644 --- a/bin/tests/system/qmin/clean.sh +++ b/bin/tests/system/qmin/clean.sh @@ -15,3 +15,4 @@ rm -f */named.run rm -f dig.out.* rm -f ns*/named.lock rm -f ans*/query.log +rm -f query*.log diff --git a/bin/tests/system/qmin/tests.sh b/bin/tests/system/qmin/tests.sh index edd76942ae..f0e61cf58a 100755 --- a/bin/tests/system/qmin/tests.sh +++ b/bin/tests/system/qmin/tests.sh @@ -35,6 +35,7 @@ AAAA a.bit.longer.ns.name.good. __EOF echo "A icky.icky.icky.ptang.zoop.boing.good." | diff ans3/query.log - > /dev/null || ret=1 echo "A icky.icky.icky.ptang.zoop.boing.good." | diff ans4/query.log - > /dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -55,6 +56,7 @@ AAAA a.bit.longer.ns.name.bad. __EOF echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans3/query.log - > /dev/null || ret=1 echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans4/query.log - > /dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -76,6 +78,7 @@ AAAA a.bit.longer.ns.name.slow. __EOF echo "A icky.icky.icky.ptang.zoop.boing.slow." | diff ans3/query.log - > /dev/null || ret=1 echo "A icky.icky.icky.ptang.zoop.boing.slow." | diff ans4/query.log - > /dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -115,6 +118,7 @@ cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 NS icky.icky.ptang.zoop.boing.good. A 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 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -126,6 +130,7 @@ $RNDCCMD 10.53.0.6 flush $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.6 > dig.out.test$n grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 echo "NS boing.bad." | diff ans2/query.log - > /dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -149,6 +154,7 @@ AAAA a.bit.longer.ns.name.bad. __EOF echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans3/query.log - > /dev/null || ret=1 echo "A icky.icky.icky.ptang.zoop.boing.bad." | diff ans4/query.log - > /dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -183,6 +189,7 @@ cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 NS icky.icky.ptang.zoop.boing.slow. A icky.icky.icky.ptang.zoop.boing.slow. __EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -202,6 +209,7 @@ NS 0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. NS 0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. __EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` @@ -254,6 +262,7 @@ cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 NS icky.icky.ptang.zoop.boing.good. A more.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 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` diff --git a/bin/tests/system/resolver/ans2/ans.pl b/bin/tests/system/resolver/ans2/ans.pl index ee0fed5b25..937c187863 100644 --- a/bin/tests/system/resolver/ans2/ans.pl +++ b/bin/tests/system/resolver/ans2/ans.pl @@ -118,7 +118,7 @@ for (;;) { # expected to be accepted regardless of the filter setting. $packet->push("authority", new Net::DNS::RR("sub.example.org 300 NS ns.sub.example.org")); $packet->push("additional", new Net::DNS::RR("ns.sub.example.org 300 A 10.53.0.3")); - } elsif ($qname =~ /broken/) { + } elsif ($qname =~ /\.broken/ || $qname =~ /^broken/) { # Delegation to broken TLD. $packet->push("authority", new Net::DNS::RR("broken 300 NS ns.broken")); $packet->push("additional", new Net::DNS::RR("ns.broken 300 A 10.53.0.4")); diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index 1c7085fda4..f2d8ab3057 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -99,6 +99,15 @@ signatures covering DNSKEY RRsets. [GL #145] + + + Support for qname minimization was added and enabled by default in + relaxed mode - in which BIND will fall back to + normal resolution should the remote server return something + unexpected during query minimization process. This default setting + might change to strict in the future. + + diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index daec139fbe..6454b68c74 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -88,33 +88,33 @@ typedef enum { /* * Options that modify how a 'fetch' is done. */ -#define DNS_FETCHOPT_TCP 0x0001 /*%< Use TCP. */ -#define DNS_FETCHOPT_UNSHARED 0x0002 /*%< See below. */ -#define DNS_FETCHOPT_RECURSIVE 0x0004 /*%< Set RD? */ -#define DNS_FETCHOPT_NOEDNS0 0x0008 /*%< Do not use EDNS. */ -#define DNS_FETCHOPT_FORWARDONLY 0x0010 /*%< Only use forwarders. */ -#define DNS_FETCHOPT_NOVALIDATE 0x0020 /*%< Disable validation. */ -#define DNS_FETCHOPT_EDNS512 0x0040 /*%< Advertise a 512 byte - UDP buffer. */ -#define DNS_FETCHOPT_WANTNSID 0x0080 /*%< Request NSID */ -#define DNS_FETCHOPT_PREFETCH 0x0100 /*%< Do prefetch */ -#define DNS_FETCHOPT_NOCDFLAG 0x0200 /*%< Don't set CD flag. */ -#define DNS_FETCHOPT_NONTA 0x0400 /*%< Ignore NTA table. */ -/* RESERVED ECS 0x0000 */ -/* RESERVED ECS 0x1000 */ -/* RESERVED ECS 0x2000 */ -/* RESERVED TCPCLIENT 0x4000 */ -#define DNS_FETCHOPT_NOCACHED 0x8000 /*%< Force cache update. */ -#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname - minimization. */ -#define DNS_FETCHOPT_QMIN_STRICT 0x00020000 /*%< Do not work around - servers that return - errors on non-empty - terminals. */ -#define DNS_FETCHOPT_QMIN_SKIP_IP6A 0x00040000 /*%< Skip some labels - when doing qname - minimization on - ip6.arpa. */ +#define DNS_FETCHOPT_TCP 0x00000001 /*%< Use TCP. */ +#define DNS_FETCHOPT_UNSHARED 0x00000002 /*%< See below. */ +#define DNS_FETCHOPT_RECURSIVE 0x00000004 /*%< Set RD? */ +#define DNS_FETCHOPT_NOEDNS0 0x00000008 /*%< Do not use EDNS. */ +#define DNS_FETCHOPT_FORWARDONLY 0x00000010 /*%< Only use forwarders. */ +#define DNS_FETCHOPT_NOVALIDATE 0x00000020 /*%< Disable validation. */ +#define DNS_FETCHOPT_EDNS512 0x00000040 /*%< Advertise a 512 byte + UDP buffer. */ +#define DNS_FETCHOPT_WANTNSID 0x00000080 /*%< Request NSID */ +#define DNS_FETCHOPT_PREFETCH 0x00000100 /*%< Do prefetch */ +#define DNS_FETCHOPT_NOCDFLAG 0x00000200 /*%< Don't set CD flag. */ +#define DNS_FETCHOPT_NONTA 0x00000400 /*%< Ignore NTA table. */ +/* RESERVED ECS 0x00000000 */ +/* 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_QMIN_STRICT 0x00020000 /*%< Do not work around + servers that return + errors on non-empty + terminals. */ +#define DNS_FETCHOPT_QMIN_SKIP_IP6A 0x00040000 /*%< Skip some labels + when doing qname + minimization on + ip6.arpa. */ /* Reserved in use by adb.c 0x00400000 */ #define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 5294807771..e1f70148b8 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -3120,8 +3120,9 @@ mark_bad(fetchctx_t *fctx) { isc_boolean_t all_bad = ISC_TRUE; #ifdef ENABLE_AFL - if (dns_fuzzing_resolver) - return ISC_FALSE; + if (dns_fuzzing_resolver) { + return (ISC_FALSE); + } #endif /* @@ -8544,7 +8545,7 @@ rctx_answer_none(respctx_t *rctx) { * the next label to query and restart it. */ if (fctx->minimized && fctx->rmessage->rcode == dns_rcode_noerror) { - return rctx_answer_minimized(rctx); + return (rctx_answer_minimized(rctx)); } /* * Workaround for broken servers in relaxed mode - if we hit an @@ -8552,7 +8553,7 @@ rctx_answer_none(respctx_t *rctx) { */ if (fctx->minimized && !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) { fctx->qmin_labels = DNS_MAX_LABELS + 1; - return rctx_answer_minimized(rctx); + return (rctx_answer_minimized(rctx)); } /* * Since we're not doing a referral, we don't want to cache any From dde66b8012af6fad93e06dd1604bd10a71ce7fc8 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Tue, 29 May 2018 15:03:01 -0700 Subject: [PATCH 12/15] nits - capitalize QNAME in the doc - regenerate options/docbook - whitespace --- bin/named/named.conf.docbook | 35 +++++++++++++++++++++-------------- bin/named/server.c | 2 +- doc/arm/master.zoneopt.xml | 1 + doc/arm/notes.xml | 10 +++++----- doc/arm/options.grammar.xml | 18 ++++++++++-------- doc/arm/slave.zoneopt.xml | 1 + doc/misc/options | 9 +++++---- lib/dns/resolver.c | 2 +- 8 files changed, 45 insertions(+), 33 deletions(-) diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 7f11110daf..442c4ab61f 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -13,7 +13,7 @@ - 2018-01-22 + 2018-05-29 ISC @@ -205,7 +205,7 @@ options { integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... } ] [ zone-directory quoted_string ] [ - in-memory boolean ] [ min-update-interval integer ]; ... }; + in-memory boolean ] [ min-update-interval ttlval ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); @@ -244,6 +244,7 @@ options { }; dns64-contact string; dns64-server string; + dnskey-sig-validity integer; dnsrps-enable boolean; dnsrps-options { unspecified-text }; dnssec-accept-expired boolean; @@ -292,14 +293,13 @@ options { fstrm-set-output-notify-threshold integer; fstrm-set-output-queue-model ( mpsc | spsc ); fstrm-set-output-queue-size integer; - fstrm-set-reopen-interval integer; + fstrm-set-reopen-interval ttlval; geoip-directory ( quoted_string | none ); - geoip-use-ecs boolean; glue-cache boolean; heartbeat-interval integer; hostname ( quoted_string | none ); inline-signing boolean; - interface-interval integer; + interface-interval ttlval; ixfr-from-differences ( primary | master | secondary | slave | boolean ); keep-response-order { address_match_element; ... }; @@ -318,10 +318,10 @@ options { masterfile-style ( full | relative ); match-mapped-addresses boolean; max-cache-size ( default | unlimited | sizeval | percentage ); - max-cache-ttl integer; + max-cache-ttl ttlval; max-clients-per-query integer; max-journal-size ( default | unlimited | sizeval ); - max-ncache-ttl integer; + max-ncache-ttl ttlval; max-records integer; max-recursion-depth integer; max-recursion-queries integer; @@ -362,6 +362,7 @@ options { preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; + qname-minimization ( strict | relaxed | disabled ); query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; @@ -401,18 +402,19 @@ options { response-padding { address_match_element; ... } block-size integer; response-policy { zone quoted_string [ log boolean ] [ - max-policy-ttl integer ] [ min-update-interval integer ] [ + max-policy-ttl ttlval ] [ min-update-interval ttlval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only quoted_string ) ] [ recursive-only boolean ] [ nsip-enable boolean ] [ nsdname-enable boolean ]; ... } [ break-dnssec boolean ] [ - max-policy-ttl integer ] [ min-update-interval integer ] [ + max-policy-ttl ttlval ] [ min-update-interval ttlval ] [ min-ns-dots integer ] [ nsip-wait-recurse boolean ] [ qname-wait-recurse boolean ] [ recursive-only boolean ] [ nsip-enable boolean ] [ nsdname-enable boolean ] [ dnsrps-enable boolean ] [ dnsrps-options { unspecified-text } ]; root-delegation-only [ exclude { quoted_string; ... } ]; + root-key-sentinel boolean; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; secroots-file quoted_string; @@ -557,7 +559,7 @@ view string [ class ] { integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... } ] [ zone-directory quoted_string ] [ - in-memory boolean ] [ min-update-interval integer ]; ... }; + in-memory boolean ] [ min-update-interval ttlval ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); @@ -595,6 +597,7 @@ view string [ class ] { }; dns64-contact string; dns64-server string; + dnskey-sig-validity integer; dnsrps-enable boolean; dnsrps-options { unspecified-text }; dnssec-accept-expired boolean; @@ -648,10 +651,10 @@ view string [ class ] { match-destinations { address_match_element; ... }; match-recursive-only boolean; max-cache-size ( default | unlimited | sizeval | percentage ); - max-cache-ttl integer; + max-cache-ttl ttlval; max-clients-per-query integer; max-journal-size ( default | unlimited | sizeval ); - max-ncache-ttl integer; + max-ncache-ttl ttlval; max-records integer; max-recursion-depth integer; max-recursion-queries integer; @@ -686,6 +689,7 @@ view string [ class ] { preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; + qname-minimization ( strict | relaxed | disabled ); query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; @@ -720,18 +724,19 @@ view string [ class ] { response-padding { address_match_element; ... } block-size integer; response-policy { zone quoted_string [ log boolean ] [ - max-policy-ttl integer ] [ min-update-interval integer ] [ + max-policy-ttl ttlval ] [ min-update-interval ttlval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only quoted_string ) ] [ recursive-only boolean ] [ nsip-enable boolean ] [ nsdname-enable boolean ]; ... } [ break-dnssec boolean ] [ - max-policy-ttl integer ] [ min-update-interval integer ] [ + max-policy-ttl ttlval ] [ min-update-interval ttlval ] [ min-ns-dots integer ] [ nsip-wait-recurse boolean ] [ qname-wait-recurse boolean ] [ recursive-only boolean ] [ nsip-enable boolean ] [ nsdname-enable boolean ] [ dnsrps-enable boolean ] [ dnsrps-options { unspecified-text } ]; root-delegation-only [ exclude { quoted_string; ... } ]; + root-key-sentinel boolean; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; send-cookie boolean; @@ -824,6 +829,7 @@ view string [ class ] { dialup ( notify | notify-passive | passive | refresh | boolean ); dlz string; + dnskey-sig-validity integer; dnssec-dnskey-kskonly boolean; dnssec-loadkeys-interval integer; dnssec-secure-to-insecure boolean; @@ -930,6 +936,7 @@ zone string [ class ] { delegation-only boolean; dialup ( notify | notify-passive | passive | refresh | boolean ); dlz string; + dnskey-sig-validity integer; dnssec-dnskey-kskonly boolean; dnssec-loadkeys-interval integer; dnssec-secure-to-insecure boolean; diff --git a/bin/named/server.c b/bin/named/server.c index bfdc2af9b7..ab14623afa 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -3690,7 +3690,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, isc_dscp_t dscp4 = -1, dscp6 = -1; dns_dyndbctx_t *dctx = NULL; unsigned int resolver_param; - const char * qminmode = NULL; + const char *qminmode = NULL; REQUIRE(DNS_VIEW_VALID(view)); diff --git a/doc/arm/master.zoneopt.xml b/doc/arm/master.zoneopt.xml index f68ace8b98..e1261b4e9a 100644 --- a/doc/arm/master.zoneopt.xml +++ b/doc/arm/master.zoneopt.xml @@ -33,6 +33,7 @@ database string; dialup ( notify | notify-passive | passive | refresh | boolean ); dlz string; + dnskey-sig-validity integer; dnssec-dnskey-kskonly boolean; dnssec-loadkeys-interval integer; dnssec-secure-to-insecure boolean; diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index f2d8ab3057..abc681dd28 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -101,11 +101,11 @@ - Support for qname minimization was added and enabled by default in - relaxed mode - in which BIND will fall back to - normal resolution should the remote server return something - unexpected during query minimization process. This default setting - might change to strict in the future. + Support for QNAME minimization was added and enabled by default + in relaxed mode, in which BIND will fall back + to normal resolution if the remote server returns something + unexpected during the query minimization process. This default + setting might change to strict in the future. diff --git a/doc/arm/options.grammar.xml b/doc/arm/options.grammar.xml index 09dbab854c..4624fbfa9d 100644 --- a/doc/arm/options.grammar.xml +++ b/doc/arm/options.grammar.xml @@ -44,7 +44,7 @@ integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... } ] [ zone-directory quoted_string ] [ - in-memory boolean ] [ min-update-interval integer ]; ... }; + in-memory boolean ] [ min-update-interval ttlval ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); @@ -83,6 +83,7 @@ }; dns64-contact string; dns64-server string; + dnskey-sig-validity integer; dnsrps-enable boolean; dnsrps-options { unspecified-text }; dnssec-accept-expired boolean; @@ -131,14 +132,13 @@ fstrm-set-output-notify-threshold integer; fstrm-set-output-queue-model ( mpsc | spsc ); fstrm-set-output-queue-size integer; - fstrm-set-reopen-interval integer; + fstrm-set-reopen-interval ttlval; geoip-directory ( quoted_string | none ); - geoip-use-ecs boolean; glue-cache boolean; heartbeat-interval integer; hostname ( quoted_string | none ); inline-signing boolean; - interface-interval integer; + interface-interval ttlval; ixfr-from-differences ( primary | master | secondary | slave | boolean ); keep-response-order { address_match_element; ... }; @@ -157,10 +157,10 @@ masterfile-style ( full | relative ); match-mapped-addresses boolean; max-cache-size ( default | unlimited | sizeval | percentage ); - max-cache-ttl integer; + max-cache-ttl ttlval; max-clients-per-query integer; max-journal-size ( default | unlimited | sizeval ); - max-ncache-ttl integer; + max-ncache-ttl ttlval; max-records integer; max-recursion-depth integer; max-recursion-queries integer; @@ -201,6 +201,7 @@ preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; + qname-minimization ( strict | relaxed | disabled ); query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; @@ -240,18 +241,19 @@ response-padding { address_match_element; ... } block-size integer; response-policy { zone quoted_string [ log boolean ] [ - max-policy-ttl integer ] [ min-update-interval integer ] [ + max-policy-ttl ttlval ] [ min-update-interval ttlval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only quoted_string ) ] [ recursive-only boolean ] [ nsip-enable boolean ] [ nsdname-enable boolean ]; ... } [ break-dnssec boolean ] [ - max-policy-ttl integer ] [ min-update-interval integer ] [ + max-policy-ttl ttlval ] [ min-update-interval ttlval ] [ min-ns-dots integer ] [ nsip-wait-recurse boolean ] [ qname-wait-recurse boolean ] [ recursive-only boolean ] [ nsip-enable boolean ] [ nsdname-enable boolean ] [ dnsrps-enable boolean ] [ dnsrps-options { unspecified-text } ]; root-delegation-only [ exclude { quoted_string; ... } ]; + root-key-sentinel boolean; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; secroots-file quoted_string; diff --git a/doc/arm/slave.zoneopt.xml b/doc/arm/slave.zoneopt.xml index 32e494a317..63c0a4acf1 100644 --- a/doc/arm/slave.zoneopt.xml +++ b/doc/arm/slave.zoneopt.xml @@ -26,6 +26,7 @@ database string; dialup ( notify | notify-passive | passive | refresh | boolean ); dlz string; + dnskey-sig-validity integer; dnssec-dnskey-kskonly boolean; dnssec-loadkeys-interval integer; dnssec-update-mode ( maintain | no-resign ); diff --git a/doc/misc/options b/doc/misc/options index 60ddaea3b2..f1e3d1023f 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -185,7 +185,7 @@ options { fstrm-set-output-queue-size ; // not configured fstrm-set-reopen-interval ; // not configured geoip-directory ( | none ); // not configured - geoip-use-ecs ; // not configured + geoip-use-ecs ; // obsolete glue-cache ; has-old-clients ; // obsolete heartbeat-interval ; @@ -205,7 +205,7 @@ options { listen-on-v6 [ port ] [ dscp ] { ; ... }; // may occur multiple times - lmdb-mapsize ; // non-operational + lmdb-mapsize ; lock-file ( | none ); maintain-ixfr-base ; // obsolete managed-keys-directory ; @@ -264,7 +264,7 @@ options { preferred-glue ; prefetch [ ]; provide-ixfr ; - qname-minimization ( strict | relaxed | disabled ); + qname-minimization ( strict | relaxed | disabled ); query-source ( ( [ address ] ( | * ) [ port ( | * ) ] ) | ( [ [ address ] ( | * ) ] port ( | * ) ) ) [ dscp ]; @@ -544,7 +544,7 @@ view [ ] { }; // may occur multiple times key-directory ; lame-ttl ; - lmdb-mapsize ; // non-operational + lmdb-mapsize ; maintain-ixfr-base ; // obsolete managed-keys { @@ -598,6 +598,7 @@ view [ ] { preferred-glue ; prefetch [ ]; provide-ixfr ; + qname-minimization ( strict | relaxed | disabled ); query-source ( ( [ address ] ( | * ) [ port ( | * ) ] ) | ( [ [ address ] ( | * ) ] port ( | * ) ) ) [ dscp ]; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index e1f70148b8..55fd1eeccc 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -9406,7 +9406,7 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) { DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, "disabling qname minimization for '%s'" " due to bad server", fctx->info); - fctx->qmin_labels = DNS_MAX_LABELS + 1; + fctx->qmin_labels = DNS_MAX_LABELS + 1; result = rctx_answer_minimized(rctx); } else if (!NOCOOKIE(query->addrinfo) && (fctx->rmessage->rcode == dns_rcode_formerr || From 1c36eed7604b465b966a7ec397c903765f514218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Wed, 30 May 2018 01:06:01 +0200 Subject: [PATCH 13/15] qname minimization: ARM entry --- doc/arm/Bv9ARM-book.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 8f2bfca31b..e2a6e7f06b 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -4665,6 +4665,26 @@ badresp:1,adberr:0,findfail:0,valfail:0] + + qname-minimization + + + This option controls QNAME minimization behaviour + in the BIND resolver. When set to strict, + BIND will follow the QNAME minimization algorithm to + the letter, as specified in RFC 7816. Setting this + option to relaxed will cause 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. disabled disables + QNAME minimization completely. The current default is + relaxed, but it might be changed to + strict in a future release. + + + + tkey-gssapi-keytab From dfa43e6dd5f34d1c589bcefa09c5ce4887b61692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Wed, 30 May 2018 18:18:55 +0200 Subject: [PATCH 14/15] CHANGES entry --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 8c4b0acf6e..4e799b2057 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +4970. [func] Add QNAME minimization option to resolver. [GL #16] + 4969. [cleanup] Refactor zone logging functions. [GL #269] 4968. [bug] If glue records are signed, attempt to validate them. From 7ec88b384d4fb027794a07643a60289a6fe4884e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Tue, 12 Jun 2018 10:20:43 +0200 Subject: [PATCH 15/15] Add qname-minimization off as an option; test fixes --- bin/named/server.c | 2 +- bin/tests/system/qmin/ns1/named.conf.in | 1 + bin/tests/system/qmin/ns5/named.conf.in | 1 + bin/tests/system/qmin/ns6/named.conf.in | 1 + bin/tests/system/qmin/ns7/named.conf.in | 1 + bin/tests/system/qmin/prereq.sh | 29 +++++++++++++++++++++++++ bin/tests/system/qmin/tests.sh | 9 ++++++++ lib/isccfg/namedconf.c | 2 +- util/copyrights | 1 + 9 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 bin/tests/system/qmin/prereq.sh diff --git a/bin/named/server.c b/bin/named/server.c index ab14623afa..c8ff38e4c9 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -4651,7 +4651,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, } else if (!strcmp(qminmode, "relaxed")) { view->qminimization = ISC_TRUE; view->qmin_strict = ISC_FALSE; - } else { + } else { /* "disabled" or "off" */ view->qminimization = ISC_FALSE; view->qmin_strict = ISC_FALSE; } diff --git a/bin/tests/system/qmin/ns1/named.conf.in b/bin/tests/system/qmin/ns1/named.conf.in index 7188e3c372..d1ab47dbdb 100644 --- a/bin/tests/system/qmin/ns1/named.conf.in +++ b/bin/tests/system/qmin/ns1/named.conf.in @@ -21,6 +21,7 @@ options { listen-on-v6 { none; }; recursion no; notify yes; + dnssec-validation no; }; zone "." { diff --git a/bin/tests/system/qmin/ns5/named.conf.in b/bin/tests/system/qmin/ns5/named.conf.in index 4d045a58ad..b4163ab066 100644 --- a/bin/tests/system/qmin/ns5/named.conf.in +++ b/bin/tests/system/qmin/ns5/named.conf.in @@ -23,6 +23,7 @@ options { qname-minimization disabled; querylog yes; resolver-query-timeout 30; + dnssec-validation no; }; key rndc_key { diff --git a/bin/tests/system/qmin/ns6/named.conf.in b/bin/tests/system/qmin/ns6/named.conf.in index 661549b407..c5fe9adc60 100644 --- a/bin/tests/system/qmin/ns6/named.conf.in +++ b/bin/tests/system/qmin/ns6/named.conf.in @@ -23,6 +23,7 @@ options { qname-minimization strict; querylog yes; resolver-query-timeout 30; + dnssec-validation no; }; key rndc_key { diff --git a/bin/tests/system/qmin/ns7/named.conf.in b/bin/tests/system/qmin/ns7/named.conf.in index 48def89b25..84472ca92a 100644 --- a/bin/tests/system/qmin/ns7/named.conf.in +++ b/bin/tests/system/qmin/ns7/named.conf.in @@ -23,6 +23,7 @@ options { qname-minimization relaxed; querylog yes; resolver-query-timeout 30; + dnssec-validation no; }; key rndc_key { diff --git a/bin/tests/system/qmin/prereq.sh b/bin/tests/system/qmin/prereq.sh new file mode 100644 index 0000000000..f570c1f4d0 --- /dev/null +++ b/bin/tests/system/qmin/prereq.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +$SHELL ../testcrypto.sh || exit 255 + +if test -n "$PYTHON" +then + if $PYTHON -c "import dns" 2> /dev/null + then + : + else + echo_i "This test requires the dnspython module." >&2 + exit 1 + fi +else + echo_i "This test requires Python and the dnspython module." >&2 + exit 1 +fi diff --git a/bin/tests/system/qmin/tests.sh b/bin/tests/system/qmin/tests.sh index f0e61cf58a..938cd7bbb1 100755 --- a/bin/tests/system/qmin/tests.sh +++ b/bin/tests/system/qmin/tests.sh @@ -26,6 +26,7 @@ $RNDCCMD 10.53.0.5 flush $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.5 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +sleep 1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 A icky.icky.icky.ptang.zoop.boing.good. A ns3.good. @@ -47,6 +48,7 @@ $RNDCCMD 10.53.0.5 flush $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.5 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +sleep 1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 A icky.icky.icky.ptang.zoop.boing.bad. A ns3.bad. @@ -69,6 +71,7 @@ $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.5 > dig.out.test$n sleep 5 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.slow. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +sleep 1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 A icky.icky.icky.ptang.zoop.boing.slow. A ns3.slow. @@ -90,6 +93,7 @@ $RNDCCMD 10.53.0.6 flush $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +sleep 1 # Duplicated NS queries are there because we're not creating # a separate fetch when doing qname minimization - so two # queries running for the same name but different RRTYPE @@ -129,6 +133,7 @@ $CLEANQL $RNDCCMD 10.53.0.6 flush $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.6 > dig.out.test$n grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +sleep 1 echo "NS boing.bad." | diff ans2/query.log - > /dev/null || ret=1 for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done if [ $ret != 0 ]; then echo_i "failed"; fi @@ -142,6 +147,7 @@ $RNDCCMD 10.53.0.7 flush $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.7 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 +sleep 1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS boing.bad. A icky.icky.icky.ptang.zoop.boing.bad. @@ -201,6 +207,7 @@ $RNDCCMD 10.53.0.6 flush $DIG $DIGOPTS -x 2001:4f8::1 @10.53.0.6 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. 1 IN PTR nee.com." dig.out.test$n > /dev/null || ret=1 +sleep 1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS 1.0.0.2.ip6.arpa. NS 8.f.4.0.1.0.0.2.ip6.arpa. @@ -221,6 +228,7 @@ $RNDCCMD 10.53.0.6 flush $DIG $DIGOPTS many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. @10.53.0.6 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. 1 IN A 192.0.2.2" dig.out.test$n > /dev/null || ret=1 +sleep 1 # We skipped after third no-delegation. cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS z.good. @@ -239,6 +247,7 @@ $RNDCCMD 10.53.0.6 flush $DIG $DIGOPTS more.icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "more.icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.2" dig.out.test$n > /dev/null || ret=1 +sleep 1 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1 NS boing.good. NS zoop.boing.good. diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 8c0b68e52a..cbcff2d856 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2952,7 +2952,7 @@ static cfg_type_t cfg_type_optional_keyref = { }; static const char *qminmethod_enums[] = { - "strict", "relaxed", "disabled", NULL + "strict", "relaxed", "disabled", "off", NULL }; static cfg_type_t cfg_type_qminmethod = { diff --git a/util/copyrights b/util/copyrights index 84bfd1ed00..0750f5dfcc 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1740,6 +1740,7 @@ ./bin/tests/system/qmin/ns5/named.conf.in CONF-C 2018 ./bin/tests/system/qmin/ns6/named.conf.in CONF-C 2018 ./bin/tests/system/qmin/ns7/named.conf.in CONF-C 2018 +./bin/tests/system/qmin/prereq.sh SH 2018 ./bin/tests/system/qmin/setup.sh SH 2018 ./bin/tests/system/qmin/tests.sh SH 2018 ./bin/tests/system/reclimit/README TXT.BRIEF 2014,2016,2017,2018